如何在Swift中创建_inline_递归闭包? [英] How do I create an _inline_ recursive closure in Swift?

查看:263
本文介绍了如何在Swift中创建_inline_递归闭包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  func f()
{
f()
}

然而,闭包不能引用自身。例如:

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

会产生以下错误:

 在其初始值中使用的变量

一个解决方法呢?如何创建一个递归闭包 inline

解决方案

有一个解决方法:

  func unimplemented< T>() - > T 
{
fatalError()
}

func递归< T,U>(f:(@escaping(((T) - > U), T)→U))→> ((T) - > U)
{
var g:((T) - > U)= {_未实现()}

g = {f g,$ 0)}

return g
}

递归是一个函数,它接收一个闭包(((T) - > U),T) - > U ,其中((T) - > U)是对闭包的剥离版本的引用,并返回一个可用函数 g



g 最初分配了一个假函数根据呼叫崩溃)。这样做的目的是为 g 的新值递归,其中 g 被传递给 f 以及输入值 T 。值得注意的是 g = {f(g,$ 0)} 中的 g 指的是它本身,而不是先前分配给它的假功能。因此,无论何时在 f 中引用((T) - > U)参数,它都是对 g ,然后引用它自己。



该函数允许内联递归,如下所示:

 递归{f,x in x!= 10? f(x + 1):success}(0)

这个函数总共有11个次,而不需要声明一个变量。



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






个人而言,我认为这是一个相当优雅的解决方案,因为我觉得它可以简化我的代码。 AY组合方法,比如下面的方法

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

会让我返回一个函数,一个逃避闭包内的转义闭包!

 递归{f in {x in x!= 10? f(x + 1):success}}(0)

上面的代码无效如果不是内部的 @escaping 属性。它还需要另外一组大括号,这使得它看起来比编写内联代码时我感觉更加冗长。


Recursion is trivial with global functions in Swift. For example:

func f()
{
    f()
}

However, a closure cannot refer to itself. For example:

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

yields the following error:

Variable used within its own initial value

Is there a workaround to this? How can I create a recursive closure inline?

解决方案

There is a workaround:

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 is a function that takes a closure (((T) -> U), T) -> U, where ((T) -> U) is a reference to a stripped version of the closure, and returns a usable function, g.

g is initially assigned a fake function (which crashes upon call). This is done to enable recursion for a new value of g, where g is passed to f along with an input value of T. It is important to note that g in g = { f(g, $0) } refers to itself, and not the fake function assigned to it earlier. So whenever the ((T) -> U) parameter is referenced in f, it is a reference to g, which in turn references itself.

This function allows for inline recursion such as in the following:

recursive { f, x in x != 10 ? f(x + 1) : "success" }(0)

This function recurs a total of 11 times, without the need to declare a single variable.

Update: This now works with Swift 3 preview 6!


Personally speaking for a moment here, I find this to be a rather elegant solution because I feel that it simplifies my code to the bare minimum. A Y combinator approach, such as the one below

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

would have me return a function, an escaping closure within an escaping closure at that!

recursive { f in { x in x != 10 ? f(x + 1) : "success" } }(0)

The code above would be invalid if not for the inner @escaping attribute. It also requires another set of braces, which makes it look more verbose than what I'm comfortable with when writing inline code.

这篇关于如何在Swift中创建_inline_递归闭包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆