arrays - 具有多个闭包的通用函数不起作用

标签 arrays swift generics closures

我想创建一个可以将数组聚合为一种类型的通用函数。我将使用一个愚蠢但简单的例子来解释。

假设我得到了这段代码:

class Entity {
    var someElement: Int
}

现在我已经把这个函数写在一个 Array extension 中了,这样我就可以在任何数组上使用它:

/**
 * An aggregation function. The first closure extracts the useful data in a new object, the second one aggregates two items of the same type in one.
 * 
 * The algorithm works from front to back
 *
 * @return the aggregated value or nil if the array is empty
 */
func aggregate<R>(translation: (T) -> R, aggregation: (R, R) -> R) -> R? {
    if count == 0 {
        return nil
    }
    if count == 1 {
        return translation(self.first!)
    }
    var calc = translation(self.first!)
    for item in 1..<count {
        calc = aggregation(calc, translation(self[item]))
    }
    return calc
}

我想像这样使用它:

let array: [Entity] = ... // something fills the array
array.aggregate(
    {
        item in 
        return item.someElement
    }, aggregation: {
        (item1, item2) in
        return item1 + item2
    }
)

但是我得到了这个疯狂的错误:Cannot convert the expression's type '((($T5) -> ($T5) -> $T4) -> (($T5) -> $T4) -> $T4, aggregation: (($T7, ($T7, $T8) -> ($T7, $T8) -> $T6) -> ($T7, ($T7, $T8) -> $T6) -> $T6, (($T7, $T8) -> ($T7, $T8) -> $T6, $T8) -> (($T7, $T8) -> $T6, $T8) -> $T6) -> (($T7, ($T7, $T8) -> $T6) -> $T6, (($T7, $T8) -> $T6, $T8) -> $T6) -> $T6)' to type 'R' .

世界上发生了什么事?在 Xcode 中,当我检查 item 的类型时, 它是 <<error type>> ,所以它甚至没有通过它的编译到达那里。我需要在我的函数调用中指定 R 是什么吗?

最佳答案

看起来 Swift 在推断第一个闭包的类型时遇到了问题。如果您更新对聚合的调用以明确提供类型:

array.aggregate(
    {
        (item: Entity)->Int in
        return item.someElement
    }, aggregation: {
        (item1, item2) in
        return item1 + item2
    }
)

它编译/运行正常。

有趣的是,如果您不使用显式返回,则推断工作正常:

array.aggregate(
    {
        item in
         item.someElement
    }, aggregation: {
        (item1, item2) in
        return item1 + item2
})

(array.aggregate({ $0.someElement},+) 也可以正常工作)

附言如果您对替代方案感兴趣,可以按如下方式重写 aggregate:

extension Array {
    func aggregate<R>(translation: T -> R, aggregation: (R, R) -> R) -> R? {

        return self.first.map { fst in
            dropFirst(self).reduce(translation(fst)) { aggregation($0, translation($1)) }
        }
    }
}

关于arrays - 具有多个闭包的通用函数不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29473340/

相关文章:

c - 如何声明任意大小的数组

java - 在不指定父类的泛型类型的情况下继承时出现不兼容类型错误

arrays - 创建单个值的数组

ruby-on-rails - 在 Ruby 中使用 max_by 查找哈希中最大数字的键

swift - 使用 Swift 将默认值添加到输入参数

swift - 为什么 Swift Playground 以 "//:"开头?

swift - 可编码 - arrayPropety [AnyObject] : Reference to member 'data' cannot be resolved without a contextual type

Java - 初始化没有泛型类型的泛型变量;

php - 我如何验证 Laravel 中的整数数组

ios - Stripe Basic PaymentIntent 确认付款错误