Null Coalescing Operator (Elvis) in Swift

A common feature in many languages, the Null Coalescing Operator is a binary operator often used to shorten expressions of the type:

   x = possiblyNullValue NCO valueIfNull

where NCO is a placeholder for the language’s operator.

Swift and nil

Swift supports a null concept through its Optional type (a Discriminated Union of sorts) which either holds a value of the underlying type or no value (indicated by nil).

Lets define a as holding optionally holding a String. Since it is initially uninitialized, its value is nil:

var a : String?
println(a)  //Output: nil

We can assign it a string value:

a = "test"
println(a)  //Output: test

Or set it back to nil:

a = nil
println(a)  //Output: nil

The typical use guard pattern for Optional in Swift is:

var z : String = ""

if let b = a {  z = b }
else { z  = "it's nil!" }
println(z) //Output: it's nil!

Null Coalescing Operator

A null coalescing operator can cut down the verbosity. Lets define a custom Swift operator ||| (three pipe chars, no spacing) for this purpose. We can express the above in more succinctly:

var z = a ||| "it's nil!"
println(z) //Output: it's nil!

And for non-nil values:

a = "123"
z = a ||| "it's nil!"
println(z) //Output: 123

The Operator

The formal definition of the operator for same types ( T ||| T):

operator infix ||| {}

@infix func |||<T> (left: T?, right: T) -> T  {
  if let l = left { return l }
  return right

Mixed Types

For mixed type cases (T ||| V, T != V) a possible overload is:

@infix func |||<T,V> (left: T?, right: V) -> Any  {
  if let l = left { return l }
  return right

We have the advantage of unwrapping the Optional, but with the overhead of unboxing the returned Any.

var x :  Int?
println(x ||| "B") //Output: B  (string)

Why “|||”

Of the characters available for custom operators in Swift, ||| comes closest to Javascript’s || OR operator which has similar uses.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s