有一个解决方法:
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 与T 的输入值一起传递给f。需要注意的是,g = { f(g, $0) } 中的 g 指的是它自己,而不是之前分配给它的假函数。因此,每当((T) -> U) 参数在f 中被引用时,它就是对g 的引用,而g 又引用了它自己。
此函数允许内联递归,如下所示:
recursive { f, x in x != 10 ? f(x + 1) : "success" }(0)
此函数一共重复11次,无需声明单个变量。
更新:现在适用于 Swift 3 preview 6!
就个人而言,我觉得这是一个相当优雅的解决方案,因为我觉得它可以将我的代码简化到最低限度。一种 Y 组合器方法,例如下面的一种
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 属性,上面的代码将无效。它还需要另一组大括号,这使得它看起来比我在编写内联代码时所习惯的更冗长。