nil-coalescing运算符会导致编译器报告歧义

时间:2015-06-06 23:22:21

标签: ios swift

我想理解为什么扩展方法有效,而nil-coalescing运算符版本告诉我有一些歧义试图编译它。

typealias SendBlock = ([NSArray]) -> Void

var callbacks = [SendBlock]()

func functionWithArgs(callback: SendBlock?) {
    callbacks.append(callback ?? { _ in })
}


func functionWithArgsExpanded(callback: SendBlock?) {
    if let cb = callback {
        callbacks.append(cb)
    } else {
        callbacks.append({ _ in })
    }
}

2 个答案:

答案 0 :(得分:3)

这是因为@autoclosure的rhs参数上使用了??。关于这一点意味着它不喜欢实际接收闭包作为被合并的东西的类型。

只是为了演示问题的位置(不要将其作为解决方法),如果在没有它的情况下重新定义??版本,那就没关系了:

typealias SendBlock = () -> Void

var callbacks = [SendBlock]()

infix operator !! { }
func !!<T>(optional: T?, defaultValue: T)->T {
    return optional != nil ? optional! : defaultValue
}


func functionWithArgs(callback: SendBlock?) {
    callbacks.append( callback !! { _ in })
}

functionWithArgs { _ in println("blah") }

// just to prove it works… prints “blah”
for x in callbacks { x() }

但是如果修改运算符以使用@autoclosure

func !!<T>(optional: T?, @autoclosure defaultValue: ()->T)->T {
    return optional != nil ? optional! : defaultValue()
}

你得到错误:

  

错误:没有更多上下文的表达式类型不明确

   callbacks.append( callback !! { _ in })
                     ^

我说这是一个错误,你应该file a report。在平均时间内,您的解决方法可能是您最好的。

答案 1 :(得分:1)

我认为这只是编译器中的一个错误。如果你在每个有SendBlock的地方替换String,它就可以正常工作。

显然,编译器在使用nil-coalescing运算符时使用Optional包装函数类型。如果你这样写,你会得到更明显的错误:

func functionWithArgs(callback: SendBlock?) {
    let sb : SendBlock = { _ in }
    callbacks.append(callback ?? sb)
}

错误内容为:“二进制运算符??无法应用于SendBlock?SendBlock类型的操作数。”对于哪一个人想回复:当然它可以!那些完全 可以应用的各种操作数:一个可选及其未包装的形式。