Swit map:错误:无法使用类型为'((_) - > _)'的参数列表调用'map'

use*_*151 4 ios swift

我无法理解为什么这个有效:

var arr = [4,5,6,7]

arr.map() {
    x in
    return  x + 2
}
Run Code Online (Sandbox Code Playgroud)

虽然这不是

arr.map() {
    x in
    var y = x + 2
    return y
}
Run Code Online (Sandbox Code Playgroud)

有错误

Playground执行失败:MyPlayground.playground:13:5:错误:无法使用类型'((_) - > _)'arr.map(){的参数列表调用'map'

Cod*_*ent 5

斯威夫特每次都无法推断出类型.即使它应该看到y = x + 2手段y也是Int如此.我的猜测是,Swift以某种顺序解析闭包,使得它在你的情况下提前不知道返回类型.

这有效:

arr.map() {
    x -> Int in
    var y = x + 2
    return y
}
Run Code Online (Sandbox Code Playgroud)


ois*_*sdk 5

这里的问题是有错误消息.一般来说,当你看到类似的东西cannot invoke .. with ...意味着编译器的类型推断没有奏效.

在这种情况下,您遇到了闭包中推理的一个限制.Swift只能推断单语句闭包的类型,而不是多语句闭包.在你的第一个例子中:

arr.map() {
  x in
  return  x + 2
}
Run Code Online (Sandbox Code Playgroud)

实际上只有一个陈述:return x + 2.但是,在第二个:

arr.map() {
  x in
  var y = x + 2
  return y
}
Run Code Online (Sandbox Code Playgroud)

有一个赋值语句(var y = x + 2),然后是返回.因此错误有点误导:它并不意味着你"不能用这种类型的参数调用map()",它意味着"我无法弄清楚x或y是什么类型".

顺便说一句,在单语句闭包中,还有另外两个可以推断出来的东西.退货声明:

arr.map() {
  x in
  x + 2
}
Run Code Online (Sandbox Code Playgroud)

变量名称本身:

arr.map() { $0 + 2 }
Run Code Online (Sandbox Code Playgroud)

但是,它们都生成相同的编译代码.所以你选择的是一个品味的问题.(例如,虽然我认为推断return看起来干净且易于阅读,但我喜欢它$0,所以我通常总是放x in或者什么,即使是非常短的闭合.但是,这显然取决于你.)

最后一件事:因为这只是语法上的东西,值得注意的()是也不需要:

arr.map { x in x + 2 }
Run Code Online (Sandbox Code Playgroud)

正如@MartinR指出的那样,编译器也可以从外部上下文推断出一些类型:

let b: [Int] = arr.map { x in
  var y = x + 2
  return y 
}
Run Code Online (Sandbox Code Playgroud)

值得记住的是这一点.(似乎只有当没有其他类型信息可用时,"单一陈述"规则才适用)

  • 次要添加:编译器也可以从*外部上下文*中推断闭包的返回类型:`let b:[Int] = arr.map {x in var y = x + 2; 返回y}`. (2认同)