-1

使用 Xcode 8 beta,swift 3 第二个扩展无法编译。我不明白这是一个快速的错误还是一个已知的限制。

extension Array {
    func scanl<T>(initial: T, combine:(Iterator.Element, T) -> T) -> [T] {
        guard let first = self.first else { return [] }
        return [initial] + Array(self.dropFirst()).scanl(initial: combine(first, initial), combine: combine)
    }
}


extension Array {
    func scanl<T>(combine: (Iterator.Element, T) -> T) -> [T] {
        guard let first = self.first else { return [] }
        return Array(self.dropFirst()).scanl(initial:first, combine:combine)// Cannot convert value of type '(Element, T) -> T' To expected argument type '(_, _) -> _'
    }
}

(Element, T) -> T 确实是函数的类型。所以我不明白为什么编译器期望 ( , ) -> __ 以及除了“我不关心类型”之外,这种类型是什么意思

4

1 回答 1

1

这不是错误或限制,编译器根本不可能在编译时确定第二个扩展first中的类型(不一定与 相同)。在您的两个闭包中,编译器都知道这是 type ,但编译器无法知道这是否也是 type 。TTIterator.ElementfirstIterator.ElementT

在您的第一个扩展中,您只使用first作为combine闭包的第一个参数,它只需要 type Iterator.Element,所以一切都很好。

但是,在您的第二个扩展中,您尝试将first作为参数传递给initial需要 type 的参数 ( ) T,并且编译器无法知道是否first真的是 type T(与用于调用 two-argumentT的闭包所使用的类型相同) ,即的is 类型。这可以很容易地通过在第二个扩展的可选绑定子句中尝试类型转换 ( )来弥补。combinescanlIterator.ElementselfTas?firstT

extension Array {
    func scanl<T>(combine: (Iterator.Element, T) -> T) -> [T] {
        guard let first = self.first as? T else { return [] }
        return Array(self.dropFirst()).scanl(initial: first, combine: combine)
    }
}

Iterator.Element如果您构造一个扫描一种类型的数组以构造另一种类型的数组的示例,那么和T不一定是相同类型的事实是显而易见的,例如

/* scant [Int] array to construct [String] array */
let foo = [1, 2, 3, 4, 5]
let bar = foo.scanl(initial: "0") { String($0) + $1 }
print(bar) // ["0", "10", "210", "3210", "43210"]

如果您只希望您的scanl方法及其收集器生成相同类型的数组(与被扫描的数组相同),那么您不需要包含 generic T,但可以使用Iterator.Elementtype 代替T上面的扩展。

于 2016-06-24T11:04:52.037 回答