斯威夫特:模糊地使用运算符' *'

时间:2016-11-17 05:04:29

标签: ios swift xcode closures swift3

尝试使用Xcode Playgrounds中的一系列闭包,我收到此错误:

Playground execution failed: error: closures.playground:11:25: error: ambiguous use of operator '*'
            {x in x * x},

我没有从语法上看到为什么这不起作用,但应该。

我最初的关闭是:

let f = {(x: Int) -> Int
    in
    return x + 42}

然后我定义了一个数组:

let closures = [f,
            {(x:Int) -> Int in return x * 2},
            {x in return x - 8},
            {x in x * x}, //This line causes the error.
            {$0 * 42}]

这些闭包中的每一个都符合f的签名,这是Xcode中的一个错误吗?如果没有,发生了什么?

对于那种情况,不应该在这种情况下推断出类型,就像在所有其他情况下明确推断的那样?

编辑:在Swift 2.2中,这似乎工作正常,但我使用的是Swift3。

2 个答案:

答案 0 :(得分:1)

如果你愿意跟随我,我有一个理论:

使用您对f的定义,以下行会在Swift 2.2和Swift 3.0中导致不同的错误:

let closures = [f, { $0 * 4.5 },{$0 * 42}]

注意第二个元素乘以一个Double,使x的推断类型也为Double,因此闭包签名不匹配。

在Swift 2.2中:"表达式的含义模糊,没有更多的上下文"

在Swift 3.0中:"异构收集文字只能推断为“任何”&#39 ;;如果这是故意的,请添加显式类型注释"

这似乎表明Swift 3.0编译器可以识别不同闭包签名的可能性,这些签名可以作为同质元素类型下载到Any

在你的例子中:

let closures = [f,
        {(x:Int) -> Int in return x * 2},
        {x in return x - 8},
        {x in x * x}, //This line causes the error.
        {$0 * 42}]

导致错误的行没有x的显式类型。 Swift 3.0允许x可能是其他类型的一种,例如一个Double,Float等,并且整个数组可能意图具有类型[Any]而不是[(Int)->Int]。因此,如果不在此位置为x声明任何显式类型,或者为closures整体声明任何显式类型,则编译器不清楚*函数的哪个版本应该是选择。也许那些x都是双打?花车?由于closures数组的类型不明确且x的类型不明确,因此编译器无法确定*的哪个版本应该在那里使用以及操作数类型是什么。

因此,您可以通过使数组的类型显式来修复错误,即:

let closures:[(Int)->Int] = [f,
        {(x:Int) -> Int in return x * 2},
        {x in return x - 8},
        {x in x * x}, //No more error.
        {$0 * 42}]

或者,通过使闭包内的x的类型明确,即:

let closures = [f,
        {(x:Int) -> Int in return x * 2},
        {x in return x - 8},
        {(x:Int) in x * x}, //No more error.
        {$0 * 42}]

在其他闭包中,与x相对的另一个操作数足以让编译器推断出x的类型,但是在生成错误的闭包中,没有什么能够最终确定这种类型。

同样,似乎这在Swift 2.2中有效,因为Swift 2.2不会将异构数组推断为类型[Any],因此假设所有闭包必须具有相同的类型。在Swift 3中,似乎允许一些模糊的可能性,这使编译器不太确定你的意图。

至少我的理论是这样的:)

答案 1 :(得分:0)

我不知道它听起来是否正确但x变量没有类型。它既没有通过操作来推断任何其他常量的任何类型。

<<错误类型>> 。所以编译器发现是ambiguos

enter image description here