如何在Swift中创建_inline_递归闭包? [英] How do I create an _inline_ recursive closure in 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
被传递给 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屋!