为什么 Swift 类型系统尝试将类型转换为错误的预期参数
why Swift type system try to convert a type into wrong expected parameter
使用Xcode8 beta,swift3第二个扩展无法编译。我不明白这是 swift 错误还是已知限制。
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 确实是函数的类型。
所以我不明白为什么编译器期望 (,) -> __
"i don't care about the type"
旁边的这种类型是什么意思
这不是错误或限制,编译器根本不可能在编译时确定 first
在您的第二个扩展中属于 T
类型(因为 T
不一定与 Iterator.Element
) 相同。在你的两个闭包中,编译器都知道 first
是 Iterator.Element
类型,但编译器不知道这是否也是 T
.
类型
在你的第一个扩展中,你只使用 first
作为 combine
闭包的第一个参数,它只需要类型 Iterator.Element
,所以一切都很好。
然而,在你的第二个扩展中,你试图将 first
作为参数传递给期望类型 T
的参数 (initial
),并且编译器无法知道 [= =12=] 确实是 T
类型(与 combine
闭包使用的相同类型 T
用于调用双参数 scanl
),即 [= self
的 15=] 属于 T
类型。这可以很容易地通过在第二个扩展的可选绑定子句中尝试将 first
类型转换 (as?
) 到 T
来弥补。
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([=11=]) + }
print(bar) // ["0", "10", "210", "3210", "43210"]
如果您只希望 scanl
方法及其收集器生成相同类型的数组(与被扫描的数组相同),那么您不需要包含通用 T
,但是可以在上面的扩展中使用 Iterator.Element
类型代替 T
。
使用Xcode8 beta,swift3第二个扩展无法编译。我不明白这是 swift 错误还是已知限制。
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 确实是函数的类型。 所以我不明白为什么编译器期望 (,) -> __ "i don't care about the type"
旁边的这种类型是什么意思这不是错误或限制,编译器根本不可能在编译时确定 first
在您的第二个扩展中属于 T
类型(因为 T
不一定与 Iterator.Element
) 相同。在你的两个闭包中,编译器都知道 first
是 Iterator.Element
类型,但编译器不知道这是否也是 T
.
在你的第一个扩展中,你只使用 first
作为 combine
闭包的第一个参数,它只需要类型 Iterator.Element
,所以一切都很好。
然而,在你的第二个扩展中,你试图将 first
作为参数传递给期望类型 T
的参数 (initial
),并且编译器无法知道 [= =12=] 确实是 T
类型(与 combine
闭包使用的相同类型 T
用于调用双参数 scanl
),即 [= self
的 15=] 属于 T
类型。这可以很容易地通过在第二个扩展的可选绑定子句中尝试将 first
类型转换 (as?
) 到 T
来弥补。
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([=11=]) + }
print(bar) // ["0", "10", "210", "3210", "43210"]
如果您只希望 scanl
方法及其收集器生成相同类型的数组(与被扫描的数组相同),那么您不需要包含通用 T
,但是可以在上面的扩展中使用 Iterator.Element
类型代替 T
。