Recreating Defer Syntax in Swift 1.2

So, a few days ago, I had the bright idea that trying to recreate some of the shiny new Swift 2.0 features in Swift 1.2 might amount to a fun challenge. I first thought about recreating guard syntax, but quickly got stuck at finding a way of calling return in the scope of a function one level up (If any of you have an idea of how to work it out please let me know). So then I found something more attainable the defer syntax.

Here it is in swift 2.0:

Output:

    test1
    tested!
    test3 b2 c3
    test2 a1

So now we have a target, save several defer functions that capture variables from the current scope, and call them right when the scope is about to end. In Swift, the objects created in a scope will get released at the end of that same scope if it ends with nothing else holding a reference to it. So a sound strategy might be to create a class that stores functions to an array and piggyback on its deinit, where we will of course call all of these functions.

Now let’s see what happens if we call this function without assigning it to a variable:

Swift 1.2 Output:

    Start Deinit
    test1
    test2
    test3

Well, that is not the result we wanted ;( It appears that if an object is not assigned to a variable in Swift 1.2 it is deinitialized immediately. Another interesting thing I discovered in my testing is that this actually works the way we want in Swift 2.0 playgrounds, although the result is the same as 1.2 from within projects, and unfortunately we can’t get a printout with running code in xcode 6 playgrounds.

Swift 2.0 Playground Output:(print function adds \n in Swift 2.0)

    test2

    test3

    Start Deinit

    test1

So now let’s abandon our quest for an exact match to Swift 2.0 syntax and settle for something that takes an extra step.

Output:

    test2
    test3
    Start Deinit
    test1

Now that we have a simple case working, let’s add nesting function calls, and captured variables into our test, and finally make use of the fer function we defined.

Output:

    NestStart
    test2
    test4-c
    Start Deinit
    test3-b
    test1-a
    NestEnd

Output in Swift 2.0 w/ actual defer calls:

    NestStart

    test2

    test4-c

    test3-b

    test1-a

    NestEnd

Swift 1.2 defer syntax achieved!

Also, thanks @matthewcheok for giving feedback on this.

  • nadohs