如何在 swift 中使用可变闭包?
How to use a variadic closure in swift?
在 Swift 的闭包中是否有使用可变参数列表的正确方法?
在 swift 中,我注意到我可以声明一个带有可变参数列表的函数,就像这样
protocol NumberType: Comparable, IntegerLiteralConvertible, IntegerArithmeticType {}
extension Int: NumberType {}
extension SequenceType where Generator.Element: NumberType {
func satisfy(closure:(args: Generator.Element...) -> ()) {
// Do something
closure(args: 1, 2, 3)
}
}
构建得很好。当我尝试使用函数时:
[1, 2].satisfy { (args) in
print (args)
}
Xcode 设法像我预期的那样自动完成,但是在关闭 args 后的括号后,Xcode 中的所有语法突出显示都消失了,我看到一条消息 "Command failed due to signal: Segmentation Fault: 11"
,它似乎只是意味着 Xcode 非常困惑。
对于上下文,我曾计划看看 Swift 是否可以编写一个函数,该函数可以 return 根据可变数量的参数(映射到获得蛮力答案)。这将是一种测试问题答案的简单方法,例如 "Given an array of Ints, find all combinations which satisfy the equation a^3 + b^3 = c^3 + d^3" 和
let answer = array.satisfy ({ return pow([=13=], 3) + pow(, 3) == pow(, 3) + pow(, 3) })
反对更优的解决方案。
"Return all the 2s" 就是
let answer = array.satisfy ({ return [=14=] == 2 })
一个for循环
编译器limitation/bug 具有单表达式闭包的参数类型推断
我认为这是编译器 w.r.t 中的当前限制 (/bug) 造成的。使用可变参数推断单行闭包中的参数类型,参见例如以下问答
- Why can't I use .reduce() in a one-liner Swift closure with a variadic, anonymous argument?
Swift 2.1 中的 inout
参数也存在类似问题(但不再出现在 2.2 中),如以下线程
中所述
查看线程 1。并试图找到在 Swift JIRA 中标记的所述错误,然而,似乎线程 1 的 OP 似乎从未为此提交过错误,毕竟。可能我只是还没有找到现有的错误报告,但如果 none 存在,应该提交一份。
当前的解决方法
在编译器的闭包参数类型推断赶上之前,可能的解决方法是
将闭包扩展到单行主体之外
// ...
[1, 2].satisfy { (args) in
() // dummy
print (args) // [1, 2, 3]
}
或者,明确包含 args
的类型,例如
[1, 2].satisfy { (args: Int...) in
print (args) // [1, 2, 3]
}
请注意,在上面的示例中,Generator.Element
解析为 Int
。
Swift 3.0-dev
的当前状态
如上所述,奇怪的是,这个错误
inout: 显然不再出现在 Swift 2.2 或 Swift 3.0-dev 中用于 inout
参数, w.r.t。
中描述的问题
- 它可能已修复,因为 bug [SR-7] 已解决 (-> Swift 2.2)
不过,好像是回归2.2->3.0-dev,w.r.t。 inout
个参数的类型推断,如 bug report [SR-892] 中所报告。例如。以下代码片段在 Swift 2.2 中有效,但在 3.0-dev 中无效(来自错误报告 [SR-7] 的最小修改片段)
func f(inout a: Int) {}
let g = { x in f(&x) } // OK 2.2, crashes 3.0-dev
variadic: 仍然存在于 Swift 2.2 以及 Swift 3.0-dev 中用于可变参数(这个线程和Q&A 1. above).
一个更简洁的错误示例:
let a: (Int...) -> () = { (args) in print(args) } // bug: crashes
let b: (Int...) -> () = { (args: Int...) in print(args) } // explicitly state argument type, OK
let c: (Int...) -> () = { (args) in (); print(args) } // extend to more than single line closure, OK
(对于 Swift 3.0-dev,使用 IBM Swift Sandbox running Swift 3.0-dev.
测试
在 Swift 的闭包中是否有使用可变参数列表的正确方法?
在 swift 中,我注意到我可以声明一个带有可变参数列表的函数,就像这样
protocol NumberType: Comparable, IntegerLiteralConvertible, IntegerArithmeticType {}
extension Int: NumberType {}
extension SequenceType where Generator.Element: NumberType {
func satisfy(closure:(args: Generator.Element...) -> ()) {
// Do something
closure(args: 1, 2, 3)
}
}
构建得很好。当我尝试使用函数时:
[1, 2].satisfy { (args) in
print (args)
}
Xcode 设法像我预期的那样自动完成,但是在关闭 args 后的括号后,Xcode 中的所有语法突出显示都消失了,我看到一条消息 "Command failed due to signal: Segmentation Fault: 11"
,它似乎只是意味着 Xcode 非常困惑。
对于上下文,我曾计划看看 Swift 是否可以编写一个函数,该函数可以 return 根据可变数量的参数(映射到获得蛮力答案)。这将是一种测试问题答案的简单方法,例如 "Given an array of Ints, find all combinations which satisfy the equation a^3 + b^3 = c^3 + d^3" 和
let answer = array.satisfy ({ return pow([=13=], 3) + pow(, 3) == pow(, 3) + pow(, 3) })
反对更优的解决方案。
"Return all the 2s" 就是
let answer = array.satisfy ({ return [=14=] == 2 })
一个for循环
编译器limitation/bug 具有单表达式闭包的参数类型推断
我认为这是编译器 w.r.t 中的当前限制 (/bug) 造成的。使用可变参数推断单行闭包中的参数类型,参见例如以下问答
- Why can't I use .reduce() in a one-liner Swift closure with a variadic, anonymous argument?
Swift 2.1 中的 inout
参数也存在类似问题(但不再出现在 2.2 中),如以下线程
查看线程 1。并试图找到在 Swift JIRA 中标记的所述错误,然而,似乎线程 1 的 OP 似乎从未为此提交过错误,毕竟。可能我只是还没有找到现有的错误报告,但如果 none 存在,应该提交一份。
当前的解决方法
在编译器的闭包参数类型推断赶上之前,可能的解决方法是
将闭包扩展到单行主体之外
// ... [1, 2].satisfy { (args) in () // dummy print (args) // [1, 2, 3] }
或者,明确包含
args
的类型,例如[1, 2].satisfy { (args: Int...) in print (args) // [1, 2, 3] }
请注意,在上面的示例中,
Generator.Element
解析为Int
。
Swift 3.0-dev
的当前状态如上所述,奇怪的是,这个错误
inout: 显然不再出现在 Swift 2.2 或 Swift 3.0-dev 中用于
中描述的问题inout
参数, w.r.t。- 它可能已修复,因为 bug [SR-7] 已解决 (-> Swift 2.2)
不过,好像是回归2.2->3.0-dev,w.r.t。
inout
个参数的类型推断,如 bug report [SR-892] 中所报告。例如。以下代码片段在 Swift 2.2 中有效,但在 3.0-dev 中无效(来自错误报告 [SR-7] 的最小修改片段)func f(inout a: Int) {} let g = { x in f(&x) } // OK 2.2, crashes 3.0-dev
variadic: 仍然存在于 Swift 2.2 以及 Swift 3.0-dev 中用于可变参数(这个线程和Q&A 1. above).
一个更简洁的错误示例:
let a: (Int...) -> () = { (args) in print(args) } // bug: crashes let b: (Int...) -> () = { (args: Int...) in print(args) } // explicitly state argument type, OK let c: (Int...) -> () = { (args) in (); print(args) } // extend to more than single line closure, OK
(对于 Swift 3.0-dev,使用 IBM Swift Sandbox running Swift 3.0-dev.
测试