递归对于Swift中的全局函数来说是微不足道的。例如:
func f()
{
f()
}
但是,闭包不能指向自身。例如:
var f: (Void -> Void) =
{
f()
}
产生以下错误:
Variable used within its own initial value
有没有解决方法?如何创建内联的递归闭包?
有一种解决方法:
func unimplemented<T>() -> T
{
fatalError()
}
func recursive<T, U>(f: (@escaping (((T) -> U), T) -> U)) -> ((T) -> U)
{
var g: ((T) -> U) = { _ in unimplemented() }
g = { f(g, $0) }
return g
}
recursive
是一个接受闭包的函数(((T) -> U), T) -> U
,其中((T) -> U)
是对闭包的剥离版本的引用,并返回一个可用函数g
。
g
最初被分配了一个伪函数(在调用时崩溃)。这样做是为了启用对新值的递归g
,其中随输入值一起g
传递到。重要的是要注意in是指自身,而不是之前分配给它的伪函数。因此,每当在中引用参数时,它都是对的引用,而后者又会引用自身。f
T
g
g = { f(g, $0) }
((T) -> U)
f
g
此功能允许进行内联递归,例如:
recursive { f, x in x != 10 ? f(x + 1) : "success" }(0)
此函数总共重复11次,而无需声明单个变量。
更新:现在可以在Swift 3预览版6中使用!
就我个人而言,我觉得这是一个相当优雅的解决方案,因为我认为它可以将我的代码简化到最低限度。AY组合器方法,例如以下一种
func recursive<T, U>(_ f: (@escaping (@escaping (T) -> U) -> ((T) -> U))) -> ((T) -> U)
{
return { x in return f(recursive(f))(x) }
}
让我返回一个函数,在那个转义闭包内一个转义闭包!
recursive { f in { x in x != 10 ? f(x + 1) : "success" } }(0)
如果不是内部@escaping
属性,则上面的代码将无效。它还需要另一组花括号,这使它看起来比我编写内联代码时所能适应的更加冗长。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句