Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么可以';我是否在带有可变匿名参数的单行Swift闭包中使用.reduce()?_Swift - Fatal编程技术网

为什么可以';我是否在带有可变匿名参数的单行Swift闭包中使用.reduce()?

为什么可以';我是否在带有可变匿名参数的单行Swift闭包中使用.reduce()?,swift,Swift,第一次关闭有效。但是,一旦我取出虚拟赋值,闭包就停止工作(addUpClosureRedFlagged)。有人知道为什么吗 let addUpClosureWorking: (Int ...) -> Int = { let dummy = "Anything" // Comment out and wait for the error... return $0.reduce(0, combine: +) } let addUpClosureRedFlagged: (Int ..

第一次关闭有效。但是,一旦我取出虚拟赋值,闭包就停止工作(addUpClosureRedFlagged)。有人知道为什么吗

let addUpClosureWorking: (Int ...) -> Int = {
  let dummy = "Anything"  // Comment out and wait for the error...
  return $0.reduce(0, combine: +)
}

let addUpClosureRedFlagged: (Int ...) -> Int = {
  return $0.reduce(0, combine: +)   // Should work, but doesn't!
}


addUpClosureWorking(1, 2, 3, 4, 5) // 15

这可能是因为编译器在处理单行闭包时进行了一些优化。如果按照闭包的类型显式接受闭包参数,则不需要伪行

let addUpClosureRedFlagged: (Int ...) -> Int = {
    (arr:Int...) -> Int in
    return arr.reduce(0, combine: +)
}
更多的是关于如何处理单行闭包

例如,该闭包的类型为()->Int。由于它是一个单行闭包,因此该单行的返回值被视为闭包的返回值,在本例中为Int。因为它不接受任何参数,所以它是()。因此类型是()->Int

但一旦添加伪行,它就变成了类型()->(),一个不接受任何参数且不返回任何值的闭包

let addEvens = {
    let dummy = 100
    [2,4,6,8].reduce(0, combine: +)
}
在您的情况下,单行闭包的类型为(x)->Int,而类型为(Int…)->Int。您可以通过不显式定义单行闭包的类型,但允许编译器推断类型来解决此问题

let addUpClosureRedFlagged = {
    (arr:Int...) -> Int in
    return arr.reduce(0, combine: +)
}

可能是编译器错误。雷达

由于您的所有参数都是同一类型的,因此您也可以使用
[Int]
参数:

let sumArray: ([Int]) -> Int = {
    return $0.reduce(0, combine: +)
}
// variadiac argument example
let fooErr1: (Int ...) -> Int = {
    return $0.reduce(0, combine: +)
} 
// or: let fooErr1: (Int ...) -> Int = { $0.reduce(0, combine: +) }
   /*  error: cannot convert value of type '(_) -> Int' 
              to specified type '(Int...) -> Int'       */

// inout argument example
let fooErr2: (inout _: Int) -> Int = {
    return $0
}
// or: let fooErr2: (inout _: Int) -> Int = { $0 } 
   /* error: cannot convert value of type '_ -> Int' 
             to specified type '(inout Int) -> Int'     */
sumArray([1,2,3,4,5])
返回正确的结果。

从当前的Swift(2.1)开始,闭包的类型推断在仅包含一行时可能会表现得有点奇怪,请参见:;期望在闭包中显式包含函数类型签名

对于variadiac和
inout
参数,存在(至少)此(编译器)“bug”/闭包限制:

let sumArray: ([Int]) -> Int = {
    return $0.reduce(0, combine: +)
}
// variadiac argument example
let fooErr1: (Int ...) -> Int = {
    return $0.reduce(0, combine: +)
} 
// or: let fooErr1: (Int ...) -> Int = { $0.reduce(0, combine: +) }
   /*  error: cannot convert value of type '(_) -> Int' 
              to specified type '(Int...) -> Int'       */

// inout argument example
let fooErr2: (inout _: Int) -> Int = {
    return $0
}
// or: let fooErr2: (inout _: Int) -> Int = { $0 } 
   /* error: cannot convert value of type '_ -> Int' 
             to specified type '(inout Int) -> Int'     */
这可以通过在闭包中显式地包含函数:s类型签名,或者在return语句之前包含任何语句(这样扩展闭包以包含多行)来避免

为什么??我已经在上面写过“bug”,但可能更多的是当前编译器在闭包类型推断方面的局限性;正如Prakdeep在他的回答中所写的,这很可能是由于Swift编译器的一些复杂之处,在这些情况下未能进行类型推断