Function 如何在Swift中创建一个_inline u递归闭包?

Function 如何在Swift中创建一个_inline u递归闭包?,function,swift,recursion,functional-programming,Function,Swift,Recursion,Functional Programming,在Swift中,递归对于全局函数来说是微不足道的。例如: func f() { f() } var f: (Void -> Void) = { f() } 但是,闭包不能引用自身。例如: func f() { f() } var f: (Void -> Void) = { f() } 产生以下错误: Variable used within its own initial value 有解决办法吗?如何创建递归闭包内联?有一个解决方法: fu

在Swift中,递归对于全局函数来说是微不足道的。例如:

func f()
{
    f()
}
var f: (Void -> Void) =
{
    f()
}
但是,闭包不能引用自身。例如:

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
}
此函数总共递归11次,无需声明单个变量

更新:这现在适用于Swift 3预览版6


就我个人而言,我觉得这是一个相当优雅的解决方案,因为我觉得它将我的代码简化到了最低限度。Y组合方法,如下面的方法

func recursive<T, U>(_ f: (@escaping (@escaping (T) -> U) -> ((T) -> U))) -> ((T) -> U)
{
    return { x in return f(recursive(f))(x) }
}

如果不是内部的
@escaping
属性,上述代码将无效。它还需要另一组大括号,这使得它看起来比我在编写内联代码时所熟悉的更详细。

限制是两个对象不能同时实例化并相互引用。一个必须在另一个之前创建。可以将函数隐式展开标记为可选。通过这种方式,您可以使用
nil
初始化函数,但“保证”它稍后会有一个值

var f: (Void -> Void)!

f = {
    f()
}
更新: 没有隐式展开选项的另一种方法:

var f: (Void -> Void)

var placeholder: (Void -> Void) = {
    f()
}

f = placeholder

虽然这是可行的,但它是丑陋的,需要我使用可选的,我宁愿不这样做。我相信没有其他选择。同样的方法也适用于
@IBOutlet
。我相信这是语言中隐含的未包装选项的主要原因。看看我自己的答案。他们承诺Swift中不会有头文件,但是这与C中的.h头有什么不同呢?update方法给出了以下错误:`变量'f'在初始化之前被闭包捕获了。这比上面Kirsteins的答案好多少?您刚刚添加了更多的样板文件,并且假设递归函数的形式为
(T->U)
(因此,如果不是这样,您必须使用类型系统进行特技飞行)。虽然不是一个理想的解决方案,但由于这个特殊的原因,隐式解包选项被引入到语言中。@SashaChedygov:如果你看一下时间戳,你会发现这是这个问题的第一个答案。我的目的是以Q/a格式分享我的知识。公平地说,我误读了时间戳。@SashaChedygov:至于我的解决方案,我的目标是严格的内联递归。