Breaking the Nil-Coalescing Operator in Swift

What is optional?

This is pretty much the first thing, every swift developer read at the time they started. Let’s understand optional in a more funnier & shorter way, Let’s say you have gone for some shopping with a wallet in your pocket. The wallet can have some money or not. If you think the wallet as an optional variable, then either it has some value or no value at all.

Before purchasing anything from a shop, you will check whether the wallet has the money or not. If money is there, then you will purchase otherwise you will skip. This is the same concept related to optional binding. But if you do not check before purchasing something, then you might be in trouble if there is no cash in the wallet. This concept is called forced unwrapping in Swift.

So forced unwrapping may result in an unwanted crash if the optional has some nil value. As a safety approach, therefore you can use optional binding. But Swift also provides a safer option, called nil-coalescing operator which requires an additional default value to return when it is applied to nil.

Breaking the ice:

Nil-coalescing operator (??) checks whether or not the optional variable is nil (a ?? b). If it is nil, then it returns the default value otherwise it returns the unwrapped value of the optional. Let’s look at how it is defined in swift-

We can use the operator like below-

But there is a small problem in ?? definition. Every time we use the nil-coalescing operator, we have to calculate the default value whether or not the optional has some value. The calculation of default value may be a complex operation or it can be a heavy read operation from disk memory. So we want to avoid calculation when it is not required because it is overhead sometimes. So to avoid the read operation, we can rewrite the ?? function definition as below-

So instead of directly providing a default value of type U, we now provide a closure type () -> U. So now defaultValue is a function of type () -> U. The code inside the defaultValue function will only be executed from else block. The above implementation has also one drawback since defaultValue is an anonymous function so we have to write the code of calculating default value inside curly braces ({ }).

We can remove those explicit curly braces from defaultValue closure by using autoclosure type attribute. This attribute implicitly converts any arguments to the ?? operator in the required closure. So we can provide the same interface which we had initially, but without requiring the user to create an explicit closure wrapping the defaultValue argument. So the definition that is used in Swift Standard Library is as follows

Now look the example used above, we have removed the curly braces from defaultValue function and it is working same like what do we write every day for a nil-coalescing operator.

A new Optional Binding:

So if we have an optional, we can unwrap the value by using optional binding, guard block or force unwrapping. But we can add one more thing to it. Suppose we have a function with below definition

In the above, if the optional has no value then we simply return nil otherwise doing some computation. We can create an extension on optional to do a safe computation.

safely function takes an argument transform of type (Wrapped) -> U. If the optional is not nil, it applies transform to it otherwise safely function returns nil.

Using this extension, we can re-write add function in a more compact and generic way.

So we can apply safely function to any optional of type Struct or Class.

🙏🙏🙏Thank you for reading!!🙏🙏🙏

Don't forget to share

You may also like...

Leave a Reply

Your email address will not be published.