了解基本的 Swift 编译器错误

Understanding a basic Swift compiler error

我明白为什么会产生编译错误:

let initialProducer = SignalProducer<Int, NoError>(value:42)
let sideEffectProducer = initialProducer.on(next: { (answer: Int) in
  return _
})

错误是

Cannot convert value of type '(Int) -> _' to expected argument type '(Int -> ())?'

所以 next 参数需要一个带有 Int 参数的闭包,当我们返回 _

时 returns Void

但为什么编译正常:

let initialProducer = SignalProducer<Int, NoError>(value:42)
let sideEffectProducer = initialProducer.on(next: { (answer: Int) in
  return ""
})

我们返回的是 String,而不是 Void 那么为什么编译器不报错呢?

_ 不是 什么。它是一个模式,或者是可以匹配任何内容的模式的一部分。它也可以用在赋值语句中,表示你不关心结果。

_ = foo()  // Ignore result returned from foo

在您的闭包中,如果您想要 return nothing,则:

return

或者如果您处于闭包的末尾,则完全省略 return。

如果您 return _,Swift 无法计算出您的闭包签名。您可以通过以下方式证明这一点:

let bar = { return _ }  // Unable to infer closure return type in current context

如果您删除 _,它可以正常编译,因为 bar 变成了 () -> ()

Swift 可以给你一个更好的错误信息,就像你尝试从一个函数 return _ 那样:

func foo() {
    return _  // '_' can only appear in a pattern or on the left side of an assignment
}

那么,为什么 return "" 有效?这是一个线索。

单行闭包有一些明显的奇怪之处。考虑以下与您的示例类似的示例:

func doit(handler: (Int) -> ()) {
    handler(17)
    print("doit is done")
}

doit() { (answer: Int) in
    //print(answer + 1)
    return ""
}

运行 这会产生输出:

doit is done

因此,就像您的示例一样,doit 需要 (Int) -> () 闭包,但我们传递的是 (Int) -> String 闭包。它有效...

但是,如果您取消注释 print(answer + 1) 行,则 return "" 会导致错误:

Unexpected non-void return in void function