Swift for Beans – about null, nil and Optional.orElse(“?!”)

As you may have gathered, I have found an interest in Swift. I have always found it easier to pick up new languages by comparing it to the one I know best, Java.

Please note, this series is intended for experienced Java Developers. I will not go into details of Java or its API. Where sensible I will provide relevant links.

Tony Hoare, inventor of null (aka nil), famously proclaimed it to be his “…billion dollar mistake”. This should not be interpreted as null/nil being evil per se, denoting the absence/not-existence of a value is essential for data processing, but rather the absence of sensible language features to handle null/nil values.

To fully appreciate this you have to jump a couple of sentences further: “… More recent programming languages like Spec# have introduced declarations for non-null references. This is the solution, which I rejected in 1965.”

Unlike Java, Optional is an integral part of Swift language. In Swift variables may not be assigned nil (null), either they have to be initialized with a value or declared as an ? optional.

var nonNill: String = "Foo"  //may not be nil  
var optNil: String?  //optional may contain nil
var optNonNill: String? = "Bar" //Bar wrapped in an optional

Any attempt to assign a non-optional variable with a nil value results in a compilation error.

Java on the other hand leaves null handling completely open, the introduction of Optional in Java 8 has provided API level functionality, sadly it has several design flaws which mitigate its usefulness (see Java 8 Optional: What’s the Point? and Why Isn’t Optional Serializable? ).

String nullString = null; //can be null
String nonNullString = "Foo"; 
Optional optNull = Optional.ofNullable(null);  //optional may contain null
Optional optNonNull = Optional.ofNullable("Bar"); 

Just like in Java optionals have to be unwrapped, this can either be done by force unwrapping the optional with !.

if optNonNill != nil {
    print(optNonNill)  //Optional("Bar")

The preferred way of handling optionals is optional binding, if the value exists it is unwrapped and assigned to a temporary variable/constant.

if let unwrapped = optNonNill {
    print(unwrapped)  //Foo
}

Force unwrapping a nil optional will still cause a runtime error, and as such should be avoided.

var unwarpped: String = optNull! 

fatal error: unexpectedly found nil while unwrapping an Optional value
Current stack trace:
0    libswiftCore.so                    0x00007fe2b790cc90 swift_reportError + 117
1    libswiftCore.so                    0x00007fe2b791e1d0 
...

In contrast Java’s null handling can seem rather archaic, with the one exception being Optional in combination with lambdas.

if(nonNullString != null) {
   ...
}

if(optNonNull.isPresent()) {
    String value = optNonNull.get();
    ...
}

//optional with lambda
optNonNull.ifPresent(x -> {...});
optNull.orElseGet(() -> {...});

In plain vanilla Java code ternary operator are often employed, to assign default values in case of null, with Java 8 Optional you can also use .orElse(…).

//Ternary operator 
String default = nullString != null ? nullString : "";

String default = optNull.orElse("");

Swift has an explicit nil coalescing operator ??, allowing for easy assignment of default values.

var myVal1: String = optNil ?? "default"
print(myVal1)  //default

//Optional binding requires an optional even with nil coalescing. 
if let myVal2 = optNil ?? Optional("default") {
   print(myVal2)  //default
} 

Swift allows optional chaining, enabling the chaining of multiple optional calls. The output will be an optional which may be nil.

var address: Address? = Address(street: "Foo Lane", city: "Bar Town", postcode: "42")
var customer: Customer? = Customer(surname: "Baz", firstname: nil, address: address)

let streetLC = customer?.address?.street?.lowercased()
print(streetLC)  //Optional("foo lane")

if let streetUC = customer?.address?.street?.uppercased() {
    print(streetUC)  //FOO LANE
}

Doing the same in Java requires a long chain of multiple null checks, or the use of null objects (see Null Object Pattern).

if(customer != null 
  && customer.getAddress() != null
  && customer.getAddress().getStreet() != null) { 
    ...     
}

Sadly it is not advisable to use Optional in domain models since they are not Serializable, which makes serializing across system boundaries (e.g. RMI, JAX-RS, JAX-WS, etc…) difficult. It can also wreak havoc when employed in passivatable context in stateful applications (such as CDI).

IBM hosts a public Swift-Sandbox, that allows you to try out Swift. This posts Swift code is published in a sandbox here for you to try out.

The next post will cover Swifts handling of variables, constants and types.

Further Resources:
Swift – The Basics
Swift – Optional Chaining
Understanding Optionals in Swift
Optionals Brocken (Java)
Java 8 Optional: What’s the Point?
IBM Swift Sandbox

Acknowledgements

I would like to thank Björn Sonntag and Robert Meyer for reviewing my posts.

One thought on “Swift for Beans – about null, nil and Optional.orElse(“?!”)”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.