This is the first part of a blog serie about modern programming languages. This part is about null safety, one of the annoying things in for example the Java programming language. How many times have you seen something like this:


 if(value != null && !value.equals("")) {  
   // do something  
 }  

or ( sometimes called defensive programming...)


 public String foo(String bar) {  
   if (bar == null) {  
     return null;  
   }  
   // do something  
 }  

Today’s IDE’s give you a warning when a variable may be referencing to null but even when you add null checks your code will be less readable, maintainable etc. So, what can we do about it?

Options

Functional programming languages model the absence of a value with an Option type of Maybe type since the start. The Scala language has an Option type and Java 8 now also has an Optional type. The main purpose of the Optional type in Java is to reduce the number of NullPointerExceptions. The combination of Optionals and Lambda expressions is really powerful. When used properly it is hard to produce NullPointerExceptions. The main problem is the readability of the code. For example, we want to check if a persons address has a country:


 public boolean hasCountry(Optional<Person> person) {  
   return person.map(p -> p.address)  
       .map(a -> a.country)  
       .isPresent();  
 }  

Because of backward compatibility the only place in Java 8 were Optionals are used is the Streams API: http://docs.oracle.com/javase/8/docs/api/java/util/class-use/Optional.html Luckily other languages have implemented more advanced mechanisms to prevent NullPointerExceptions.

Safety

In Kotlin, a language developed by Jetbrains, this can be expressed more easily in a one liner. An optional value is marked with a question mark and optionals can be chained:


 class Person {  
   val address: Address?  
   constructor(address: Address?) {  
     this.address = address  
   }  
 }  
 class Address {  
   var country: String?  
   var city: String  
   constructor(country: String?, city: String) {  
     this.country = country  
     this.city = city  
   }  
 }  
 fun hasCountry(person: Person?) : Boolean {  
   return person?.address?.country != null;  
 }  

The Kotlin compiler enforces that you can not pass null values to non-optional variables!

The Swift language is developed by Apple to replace the Objective-C language and claims to be a safe language. The language itself still has notion of null values (nil).


 struct Person {  
   var name : String;  
   var address : Address?  
 }  
 struct Address {  
   var city : String  
   var country: String?  
 }  
 let address = Address(city: "Utrecht", country: nil)  
 let person = Person(name: "test", address: address)  
 print(person.address?.country == nil)  

If we don’t declare the country variable as an optional string the code above will not compile.

The Rust language is designed to be a safe alternative to the C language and has some really cool safety features. For example you can never access a variable that is not initialised. See the first line in the main function, country must have a default value, if we do not declare a default value the code will not compile.


 struct Person {  
  name: String,  
  address: Option<Address>,  
 }  
 struct Address {  
  city: String,  
  country: Option<String>,  
 }  
 fn main() {  
  let address = Address { city: "utrecht".to_string(), country: Default::default()};  
  let person = Person { name: "a person".to_string(), address: Some(address) };  
  println!("Country is set? {}", person.address.unwrap().country.is_some());  
 }  

The compiler of both Rust and Swift is really helpful for the programmer. You have to explicitly declare variables as options in order to use the null reference in Swift. The Rust language does not know about the null reference at all.

More info about:

Kotlin - https://kotlinlang.org/
Swift - https://developer.apple.com/swift/
Rust - https://www.rust-lang.org/