Recursive block in Swift

I am trying to convert this block of code from Objective-C (taken from https://gist.github.com/mikeash/1254684 ) to Swift. I have used it successfully to iterate over a block of code based on the results of API calls. Is there a better way to do this in Swift?

dispatch_block_t recursiveBlockVehicle(void (^block)(dispatch_block_t recurse)) {
    return ^{
        block(recursiveBlockVehicle(block));
    };
}

      

Any help is appreciated.

+3


source to share


1 answer


Here is a direct translation of your obj-c version:

func recursiveBlockVehicle(block: (()->Void)->Void) -> ()->Void {
    return { block(recursiveBlockVehicle(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!

      

(Ive aligned dispatch_block_t

as it is not needed in the Swift version, but you can use it instead ()->Void

if you like)

For the 1 parameter version, you can use generics, not obj-c id

, so it can create one parameter recursive blocks like:

func recursiveBlockVehicle<T>(block: (T, T->Void)->Void) -> T->Void {
    return { param in block(param, recursiveBlockVehicle(block)) }
}

let block1: Int->Void = recursiveBlockVehicle { i, recurse in
    if i > 0 {
        print("\(i) ")
        recurse(i-1)
    }
    else {
        println("blastoff!")
    }
}

block1(5)  // prints 5 4 3 2 1 blastoff!

      

(and Swift overloading means you don't have to give them different names)



... and if you want your recursive function to return a value:

func recursiveBlockVehicle<T,U>(block: (T, T->U)->U) -> T->U {
    return { (param: T)->U in block(param, recursiveBlockVehicle(block)) }
}

let factorial: Int->Int = recursiveBlockVehicle { i, factorial in
    return i > 1 ? i*factorial(i-1) : 1
}

factorial(4)  // returns 24

      

Please note that this is the last one thing that you need - because T

, and U

can be Void

, it also serves for the purpose of the non-return of the zero option, although you need to write your circuit to take two arguments (the first of which you can ignore, because itll be invalid ), i.e:

let block: ()->() = recursiveBlockVehicle { _, recurse in

      

If you like this stuff, you should check out the 2014 WWDC Advanced Swift video , which is an example of an imaginary recursive caller function.

+5


source







All Articles