可以这样说(arr是一个数组):
arr
let arrenum = Array(arr.enumerated())
那么为什么这样说不合法?
extension Array { func f() { let arrenum = Array(self.enumerated()) // error: type of expression is ambiguous without more context } }
编辑 似乎这是一种解决方法:
extension Array { func f() { typealias Tup = (offset:Index, element:Element) let arrenum = Array<Tup>(self.enumerated()) } }
但是为什么需要那?(对吗?)
这是一个已知的错误(SR-1789)。Swift目前具有一项功能,您可以在自己的主体内引用泛型类型,而不必重复其占位符类型- 编译器会为您推断出它们与的类型相同self。
self
例如:
struct S<T> { func foo(_ other: S) { // parameter inferred to be `S<T>`. let x = S() // `x` inferred to be `S<T>`. } } extension S { func bar(_ other: S) {} // same in extensions too. }
这很方便,但是您遇到的错误是,即使错误,Swift也会 始终 做出这种推断。
因此,在您的示例中:
Swift会将代码解释为let arrenum = Array<Element>(self.enumerated()),就像您身在其中一样Array<Element>。这是不正确的,因为会enumerated()产生一系列偏移元素元组对–应该推断Array是Swift Array<(offset: Int, element: Element)>。
let arrenum = Array<Element>(self.enumerated())
Array<Element>
enumerated()
Array
Array<(offset: Int, element: Element)>
您已经发现的一种解决方法是显式指定占位符类型,以防止编译器做出这种错误的推断。
extension Array { func f() { let arrenum = Array<(offset: Int, element: Element)>(self.enumerated()) } }
另一个可能的解决方法似乎是使用完全限定的类型,例如:
extension Array { func f() { let arrenum = Swift.Array(self.enumerated()) } }
看来Swift不会对完全限定的类型进行相同的推断(不过我不确定您是否应该依赖这个事实)。
最后,值得注意的是Array,您可以map(_:)代替使用来避免初始化问题,而不必完全调用:
map(_:)
extension Array { func f() { let arrenum = self.enumerated().map { $0 } } }
就像初始化程序调用一样,它将给您返回一组偏移元素对。