我一直在尝试将这段代码从Objective-C(取自https://gist.github.com/mikeash/1254684)转换为Swift.我已经成功地使用它来根据API调用的结果重复一段代码.在Swift中有更好的方法吗?
dispatch_block_t recursiveBlockVehicle(void (^block)(dispatch_block_t recurse)) {
return ^{
block(recursiveBlockVehicle(block));
};
}
Run Code Online (Sandbox Code Playgroud)
任何帮助表示赞赏.
这是你的obj-c版本的直接翻译:
func recursiveBlockVehicle(block: @escaping (()->Void)->Void) -> ()->Void {
return { block(recursiveBlockVehicle(block: block)) }
}
// test usage
var i = 5
let block = recursiveBlockVehicle { recurse in
if i > 0 {
print("\(i--) ")
recurse()
}
else {
println("blastoff!")
}
}
block() // prints 5 4 3 2 1 blastoff!
Run Code Online (Sandbox Code Playgroud)
(我已经提到了,dispatch_block_t因为它在Swift版本中没有必要,但你可以使用它而()->Void不是代替你喜欢)
对于1参数版本,您可以使用泛型而不是obj-c id方法,因此它可以创建类型安全的单参数递归块:
func recursiveBlockVehicle<T>(block: @escaping (T, (T)->Void)->Void) -> (T)->Void {
return { param in block(param, recursiveBlockVehicle(block: block)) }
}
let block1: (Int)->Void = recursiveBlockVehicle { i, recurse in
if i > 0 {
print("\(i) ")
recurse(i-1)
}
else {
print("blastoff!")
}
}
block1(5) // prints 5 4 3 2 1 blastoff!
Run Code Online (Sandbox Code Playgroud)
(和Swift重载意味着你不必给它们不同的名字)
...如果你想让你的递归函数返回一个值:
func recursiveBlockVehicle<T,U>(block: @escaping (T, (T)->U)->U) -> (T)->U {
return { (param: T)->U in block(param, recursiveBlockVehicle(block: block)) }
}
let factorial: (Int)->Int = recursiveBlockVehicle { i, factorial in
return i > 1 ? i*factorial(i-1) : 1
}
factorial(4) // returns 24
Run Code Online (Sandbox Code Playgroud)
请注意,这最后一个是你真正需要的只有一个-因为T和U可以Void,它所服务的目的,零参数无返回一个太,但你必须写封锁采取两个参数(其中第一个你可以忽略,因为它将是无效的,即:
let block: ()->() = recursiveBlockVehicle { _, recurse in
Run Code Online (Sandbox Code Playgroud)
如果您喜欢这种东西,您应该查看2014 WWDC Advanced Swift视频,它是一个记忆递归函数调用者的例子.