Swift: Embettering solutions

With Swift, there’s almost always a better way to do things and when you get to that better way, it just rings with “of course”-ness.

As usual, this started as a question from a participant in #swift-dev. “This doesn’t work,” he said, and pasted the following.

func continueGame() {
    if self.gameLogic.count == 0 {
        return
    }
    self.gameLogic[0]()
    self.gameLogic.removeAtIndex(0)
}

So I started kicking the wheels on it. To get going, I decided to use the following array of closures to test my approaches.

[Void -> Void] = [{println("one")}, {println("two")}, {println("three")}]

First, I explained about using a generator and the next() function:

var myarray : [Void -> Void] = [{println("one")}, {println("two")}, {println("three")}]
var mygenerator = myarray.generate()

if let closure = mygenerator.next() {
closure()
}

if let closure = mygenerator.next() {
closure()
}

if let closure = mygenerator.next() {
closure()
}

That wasn’t practical for a generalized implementation.So I built a few loops that eventually ended up like this:

while true {
    if let closure = mygenerator.next() {
        closure()
    } else {
        break
    }
}

But Ken Ferry took one look at that, laughed, and suggested the following (far more elegant) solution instead:

while let closure = mygenerator.next() {closure()}

Beautiful and simple. Thanks, Ken.

2 Comments

  • Using a for in loop seems the swiftiest way to do this to me

    var myarray : [Void -> Void] = [{println(“one”)}, {println(“two”)}, {println(“three”)}]

    for closure in myarray {
    closure()
    }

    no direct messing with a generator necessary

  • If the goal is to execute and remove all one by one, then another solution is:

    var myarray : [Void -> Void] = [{println(“one”)}, {println(“two”)}, {println(“three”)}]

    for _ in indices(myarray) { myarray.removeLast()() }