Swift Array()强制模棱两可,没有更多上下文,但仅在扩展中 [英] Swift Array() coercion ambiguous without more context — but only in extension

查看:107
本文介绍了Swift Array()强制模棱两可,没有更多上下文,但仅在扩展中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是合法的说法(arr是一个数组):

It is legal to say this (arr is an Array):

let arrenum = Array(arr.enumerated())

那么为什么这样说是不合法的?

So why isn't it legal to say this?

extension Array {
    func f() {
        let arrenum = Array(self.enumerated())
        // error: type of expression is ambiguous without more context
    }
}


编辑,这似乎是一种解决方法:


EDIT It seems this is a workaround:

extension Array {
    func f() {
        typealias Tup = (offset:Index, element:Element)
        let arrenum = Array<Tup>(self.enumerated())
    }
}

但是为什么需要这样做? (是吗?)

But why is that needed? (And is it right?)

推荐答案

这是一个已知的错误( SR-1789 ). Swift目前具有一项功能,您可以在自己的主体内引用泛型类型,而不必重复其占位符类型-编译器会为您推断出它们与self的类型相同.

This is a known bug (SR-1789). Swift currently has a feature where you can refer to a generic type within its own body without having to repeat its placeholder type(s) – the compiler will infer them for you to be the same as the type of 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也会总是进行这种推断.

This is pretty convenient, but the bug you're running into is the fact that Swift will always make this inference, even if it's incorrect.

因此,在您的示例中:

extension Array {
    func f() {
        let arrenum = Array(self.enumerated())
        // error: type of expression is ambiguous without more context
    }
}

Swift将代码解释为let arrenum = Array<Element>(self.enumerated()),就像您在Array<Element>正文中一样.这是不正确的,因为enumerated()会产生一系列偏移元素元组对– Swift应该将Array推断为Array<(offset: Int, element: Element)>.

Swift interprets the code as let arrenum = Array<Element>(self.enumerated()), as you're in the body of Array<Element>. This is incorrect, because enumerated() yields a sequence of offset-element tuple pairs – Swift should have inferred Array to be Array<(offset: Int, element: Element)> instead.

您已经发现的一种解决方法是显式指定占位符类型,以防止编译器做出这种错误的推断.

One workaround, which you've already discovered, is to explicitly specify the placeholder type in order to prevent the compiler from making this incorrect inference.

extension Array {
  func f() {
    let arrenum = Array<(offset: Int, element: Element)>(self.enumerated())
  }
}

另一种可能的解决方法似乎是使用标准类型,例如:

Another possible workaround appears to be using the fully-qualified type, for example:

extension Array {
  func f() {
    let arrenum = Swift.Array(self.enumerated())
  }
}

Swift似乎没有对完全限定的类型进行相同的推断(不过我不确定您是否应该依靠这一事实).

as it appears Swift doesn't do the same inference for fully-qualified types (I'm not sure if you should rely on this fact though).

最后,值得注意的是,您可以使用map(_:)来完全避免问题,而不是调用Array的初始化程序:

Finally it's worth noting that instead of doing a call to Array's initialiser, you could use map(_:) instead to avoid the issue entirely:

extension Array {
  func f() {
    let arrenum = self.enumerated().map { $0 }
  }
}

与初始化程序调用一样,它会给您返回一组偏移量元素对.

which, like the initialiser call, will give you back an array of offset-element pairs.

这篇关于Swift Array()强制模棱两可,没有更多上下文,但仅在扩展中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆