Search code examples
swiftoperatorsnull-coalescing-operatorassociativitycustom-operator

Why is Nil coalescing operator Right Associative?


Shouldn’t it be Left Associative?

I think

let a = b ?? c ?? d

is grouped like

let a = (b ?? c) ?? d

not

let a = b ?? (c ?? d)

But it is declared as a Right Associative. Do I misunderstand or miss something?


Solution

  • I think it's an optimization. Left or right association doesn't change the result.

    This:

    (b ?? c) ?? d
    

    evaluates b ?? c, and its result is used as the left side of x ?? d. So even if b is not null, the coalescing operator is executed 2 times.

    In this case instead

    b ?? (c ?? d)
    

    if b is not nil, the expression at the right side is not evaluated, hence not executed


    Addendum

    To prove that, I made a simple test: I (re)defined the nil coalescing operator:

    infix operator !!! {
        associativity left
        precedence 110
    }
    
    func !!!<T>(optional: T?, defaultValue: @autoclosure () -> T?) -> T? {
        if let value = optional {
            println(optional)
            return value
        }
    
        let def = defaultValue()
        println(def)
        return def
    }
    

    With this test data:

    let a: String? = "a"
    let b: String? = "b"
    let c: String? = "c"
    
    let d = a !!! b !!! c
    

    Using associativity left, this is what's printed to the console:

    Optional("a")
    Optional("a")
    

    whereas changing the associativity to right, the output is:

    Optional("a")
    

    That means when using right associativity the right side of the operator is ignored if the left is not nil.