这是一个非常简单的递归函数:
func lap (n: Int) -> Int {
if n == 0 { return 0 }
return lap (n - 1)
}
如果我想将其转换为闭包:
let lap = {
(n: Int) -> Int in
if n == 0 { return 0 }
return lap (n - 1)
}
我收到编译错误:“变量在其自己的初始值中使用”
答案 0 :(得分:11)
您可以通过两步分配来解决它
var lap : (Int) -> Int!
lap = {
(n: Int) -> Int in
if n == 0 { return 0 }
return lap(n - 1)
}
或者您可以使用Y combinator
func Y<T, R>( f: (T -> R) -> (T -> R) ) -> (T -> R) {
return { t in f(Y(f))(t) }
}
let lap = Y {
(f : Int -> Int) -> (Int -> Int) in
return { (n : Int) -> Int in return n == 0 ? 0 : f(n - 1) }
}
// with type inference
let lap2 = Y {
f in { n in n == 0 ? 0 : f(n - 1) }
}
这是@zneak找到的内存泄漏问题的解决方法(它没有内存泄漏但是捕获了错误的值)
func f(n: Int) {
var f = Foo()
var lap: @objc_block (Int)->Int = { $0 }
var obj: NSObject = reinterpretCast(lap)
lap = {
[weak obj] (n: Int) -> Int in // unowned will cause crush
if n == 0 { return 0 }
println(f)
var lap2 : @objc_block (Int)->Int = reinterpretCast(obj)
return lap2 (n - 1)
}
lap(n)
}
for i in 0..<5 {
f(i)
}
class Foo {
init() {
println("init");
}
deinit {
println("deinit")
}
}
答案 1 :(得分:10)
编辑使用嵌套函数已经使用Swift 2解决了这个问题。 Apple建议使用此代码:
func f(n: Int) {
func lap(n: Int) -> Int {
if n == 0 { return 0 }
print(n)
return lap(n - 1)
}
lap(n)
}
for i in 0..<1000000 { f(i) }
虽然目前的例子并不明显,但所谓的局部函数捕获了封闭范围的局部。
使用定位函数不会泄漏,而闭包会。但是,很明显,lap
在这种情况下无法重新分配。
我收到了来自Apple的Joe Groff的电子邮件,声称他们仍然计划在以后将关闭作为弱变量和可变变量捕获。但这确实证实,除了本地功能之外,现在没有办法做到这一点。
您当前的解决方案中存在内存泄漏:lap
的闭包具有对自身的强引用,这意味着它无法释放。通过附带Leaks仪器启动以下程序可以轻松验证这一点:
import Foundation
func f(n: Int) {
var lap: (Int)->Int = { $0 }
lap = {
(n: Int) -> Int in
if n == 0 { return 0 }
println(n)
return lap (n - 1)
}
lap(n)
}
for i in 0..<1000000 {
f(i)
}
不幸的是,因为explicit capture syntax无法应用于闭包类型(您会收到错误消息,说明&#34;&#39;无主&#39;无法应用于非类型&#39;( Int) - &gt; Int&#39;&#34;),似乎没有简单的方法来实现这一点而不会泄漏。我提交了一份关于它的错误报告。
答案 2 :(得分:3)
这是对我自己的问题的回应:
var lap: (Int)->Int = { $0 }
lap = {
(n: Int) -> Int in
if n == 0 { return 0 }
println(n)
return lap (n - 1)
}
答案 3 :(得分:0)
这个怎么样:
let lap = {(Void) -> ((Int) -> Int) in
func f(n: Int) -> Int {
print(n)
return n == 0 ? 0 : f(n - 1)
}
return f
}()
这很简单,我刚刚在闭包中定义了一个递归的局部函数,它返回了函数。
但是,我不得不说@Bryan Chen关于 Y组合器的答案很棒。
答案 4 :(得分:0)
我遇到了同样的问题,对那里的任何内容都不满意,所以我创建了一个库,并在GitHub上提供了它。
使用这个库(使用Swift 3.0),您的代码将如下所示:
let lap = Recursion<Int, Int> { (n, f) in
n == 0 ? 0 : f(n-1)
}.closure