Search code examples
swiftoption-typeoptional-chaining

Is Swift optional chaining lazily evaluated left-to-right?


The documentation doesn't seem to mention anything explicit about the order of optional chaining evaluation, just that:

Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil.

Might seem obvious but I needed to confirm exactly what happens and thought it might be helpful for others. e.g. are we able to safely do this kind of thing?

    opVar?.someObject.someMethod(opVar!)

Solution

  • Optional chains are lazily evaluated left-to-right as you'd expect. The first optional in the chain to fail stops any further evaluation of the chain.

    // Playground test for left-to-right lazy evaluation.
    struct C {
        static var i = 0
        func chain(count: Int) -> C? {
            print("Expected \(count) -> \(C.i)")
            assert(count == C.i)
            C.i += 1
            return C.i > 2 ? nil : self
        }
    }
    
    let c = C()
    c.chain(0)?.chain(1)?.chain(2)?.chain(3)!.chain(4)!
    

    Output

    Expected 0 -> 0
    Expected 1 -> 1
    Expected 2 -> 2