【问题标题】:Swit map: error: cannot invoke 'map' with an argument list of type '((_) -> _)'切换地图:错误:无法使用类型为“((_)-> _)”的参数列表调用“地图”
【发布时间】:2015-09-11 14:54:41
【问题描述】:

我不明白为什么这个有效:

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

arr.map() {
    x in
    return  x + 2
}

这个不是

arr.map() {
    x in
    var y = x + 2
    return y
}

有错误

游乐场执行失败:MyPlayground.playground:13:5: 错误: 无法使用类型为“((_)-> _)”的参数列表调用“地图” arr.map() {

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    这里的问题是有错误信息。一般来说,当你看到像cannot invoke .. with ... 这样的东西时,这意味着编译器的类型推断刚刚不起作用。

    在这种情况下,您遇到了闭包内推理的限制之一。 Swift 只能推断出 single-statement 闭包的类型,而不能推断出多语句闭包的类型。在您的第一个示例中:

    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 是什么类型”。

    顺便说一句,在单语句闭包中,还有两件事可以推断出来。返回语句:

    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)

    【讨论】:

    • 小补充:编译器也可以从外部上下文推断闭包的返回类型:let b : [Int] = arr.map { x in var y = x + 2 ; return y }.
    • 对不起,不得不接受Zoff的回答,他是第一个
    【解决方案2】:

    Swift 不能每次都推断类型。即使它应该看到y = x + 2 意味着y 也是Int。我的猜测是 Swift 会以某种顺序解析闭包,这使得它在你的情况下提前不知道返回类型。

    这行得通:

    arr.map() {
        x -> Int in
        var y = x + 2
        return y
    }
    

    【讨论】:

    • 是的,这实际上解决了如何解决问题。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 2017-03-20
    • 2018-04-08
    • 1970-01-01
    相关资源
    最近更新 更多