這裏的問題是存在的錯誤消息。一般來說,當你看到類似cannot invoke .. with ...
這意味着編譯器的類型推斷剛剛沒有工作。
在這種情況下,您遇到了關閉中推斷的侷限性之一。 Swift只能推斷出單個語句的類型,而不是多語句的類型。在你的第一個例子:
arr.map() {
x in
return x + 2
}
有實際上是隻有一個語句:return x + 2
。然而,在第二:
arr.map() {
x in
var y = x + 2
return y
}
有一個賦值語句(var y = x + 2
),並然後回報。所以這個錯誤有點誤導:它並不意味着你「不能用這種類型的參數調用map()」,它的意思是說「我找不出什麼類型的x或y是什麼」。
順便說一句,在單語句閉包中,還有兩件事情可以推斷出來。 return語句:
arr.map() {
x in
x + 2
}
和變量名本身:
arr.map() { $0 + 2 }
這一切都產生相同的編譯代碼,但。所以這是你選擇的一個品味的問題。 (例如,雖然我認爲推斷return
看起來乾淨,更容易閱讀,但我不知道像$0
那樣,所以我通常總是會把x in
什麼東西,即使是非常短的封閉也是如此,這取決於你。)
的最後一件事:因爲這是一切真的只是語法的東西,這是值得注意的是,不需要()
之一:
arr.map { x in x + 2 }
由於@MartinR指出,編譯器可以推斷出某些類型從外部環境來看:
let b: [Int] = arr.map { x in
var y = x + 2
return y
}
這值得銘記。(it seems that the "one-statement" rule only applies when there's no other type info available)
小增加:編譯器可以從* outer context *:'let b:[Int] = arr.map {x in var y = x + 2;}中推斷出閉包的返回類型。返回y}'。 –
對不起,必須接受Zoff的回答,他是第一個 – user1284151