Do you need help on a specific subject? Use the contact form (Request a blog entry) on the right hand side.

2016-08-04

while let | Swift gotcha

Consider the following:

class LinkedList {
    var previous: LinkedList?
    var next: LinkedList?
    var payload: String
    init(previous: LinkedList?, value: String) {
        self.previous = previous
        payload = value
        previous?.next = self
    }
    func walkBack() -> String {
        var str = payload
        let link = self
        while let link = link.previous {
            str = link.payload + str
        }
        return str
    }

}

It should be clear what the intention is of the function walkBack() is: it should concatenate all payloads and return that as a string.

But the function contains an error that might not bite immediately.

For the top level element of the list, the function wil work fine. It simply returns its own payload.

But for the elements that have a previous element the function will go into an endless loop.

Why? that becomes clear when we change the definition of link from a let to a var:


This shows that the value of link never changes. The while loop creates its own instance of link each time it loops. And since the value for that link is derived from the value of the link outside the loop it will loop until the app runs out of memory.

Simply replacing the outside-the-loop definition of link to "outsideLink" clarifies this better:

    func walkBack() -> String {
        var str = payload
        let outsideLink = self
        while let link = outsideLink.previous {
            str = link.payload + str
        }
        return str

    }

Now it is clear that link is never modified to anything else but the previous element of self. In fact we could better write this as:

    func walkBack() -> String {
        var str = payload
        while let link = self.previous {
            str = link.payload + str
        }
        return str
    }

Which of course we would never do since the error is now obvious!

The tricky thing is of course that we (I?) get used to simply accepting the suggestions of the compiler.

Lesson for self: Don't automatically accept the compiler suggestions!

Oh, and btw, the right way to do this is:

    func walkBack() -> String {
        var str = payload
        var link = self.previous
        while link != nil {
            str = link!.payload + str
            link = link!.previous
        }
        return str

    }

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

No comments:

Post a Comment