Swift: nil coalescing

A few nice things this morning

// See: http://twitter.com/iMartinKiss/status/494456905885319169
extension Optional {
    func unwrap(#defaultValue: @auto_closure () -> T) -> T {
        return self ? self! : defaultValue()
    }
}

// See: http://ijoshsmith.com/2014/07/24/nil-coalescing-operator-in-swift/
operator infix !! {}
@infix func !! <T> (value: T?, defaultValue: @auto_closure () -> T) -> T
{
    return value ? value! : defaultValue()
}

And from Phil Holland:

func defaultFallback<T>(a: T?, b: @auto_closure () -> T) -> T { return a ? a! : b() }
func defaultFallback<T: LogicValue>(a: T, b: @auto_closure () -> T) -> T { return a ? a : b() }
func defaultFallback<T: Integer>(a: T, b: @auto_closure () -> T) -> T { return (a != T.allZeros) ? a : b() }
func defaultFallback<T: FloatingPointNumber>(a: T, b: @auto_closure () -> T) -> T { return (!a.isZero && !a.isNaN) ? a : b() }

4 Comments

  • The !! operator (or |||, which is the other thing people use) should be made right-associative (IIRC). That allows you to create a chain of several possibly-optional defaults, ending with a non-optional last default, like “this !! that !! theOther !! 0”.

    It should probably also be set to the same precedence as the logical operators, but I haven’t looked up what precedence level they’re at.

    • I went with 100 for mine (which happens to be the default as well) because that’s the precedence of the ?: ternary. The || and && operators are precedence 110 and 120 (respectively), but they’re also left-associative.

      Ideally Swift would provide a `x ?: y` shorthand for this operator, similar to C’s ?: shorthand, which would presumably be right-associatve precedence 100. I filed a radar on this already.

  • For the !! operator, my preference is !||, which I posted a gist of at https://gist.github.com/kballard/5fa08916c1f480bae38d.

  • Also the `unwrap` method, while cute, doesn’t work for any type `T?!`. It will unwrap the outer implicitly-unwrapped optional and call the `unwrap()` method on the inner `T?` instead. Presumably you could write a similar extension on ImplicitlyUnwrappedOptional, though I haven’t tested that.

    For some reason this doesn’t happen with operators. `T?!` will be converted to `T??` when used with the operator version (like the one I linked to).