Historically, the use of null has often been referred to as the billion dollar mistake. It has led to more problems than solutions
Tony Hoare introduced Null references in ALGOL W back in 1965 “simply because it was so easy to implement”, says Mr. Hoare. He talks about that decision considering it “my billion-dollar mistake”.
Let us look at the following code in Java which is all too familiar to us
[sourcecode language=”java”]
public class MapJavaTester {
public static void main (String [] args){
callMapper();
}
private static void callMapper() {
Map m = new HashMap<String, String>();
m.put("India","1");
m.put("SriLanka","2");
System.out.println(m.get("India"));
System.out.println(m.get("Indiaa"));
}
}
[/sourcecode]
As you would quickly notice we would get a “null” with the second sop. What is this null? In an object-oriented world, we would expect it to be an object right? Wrong! Null is a keyword in Java and not an object, as a result of which we cannot call any methods on it. To circumvent this issue there are options available to create a Null object of your own so that your logic can execute without doing null comparisons. We detail out the null object here as one of the best practices.
How does Scala do it? As a best practice, Scala suggests that when there are variables and functions which may or may not refer to a value then it is better to use an Option type in that case. An Option class has 2 subclasses, Some and None. As you would decipher, it returns Some when there is some value returned which is not null, and None when there is no value returned.
This is implemented as a part of Map in Scala, where depending on the key against which we are trying to extract a value, we might get a Some or a None. Since both of these are objects, we can call methods on them. Let us look at it in action
[sourcecode language=”scala”]
object MapTester{
def main(args: Array[String]) {
createMap()
}
def createMap(){
val countries = Map("India"->"1", "Pakistan"->"3", "SriLanka"->"2")
println("India " + countries.get("India"))
println("Indiaa "+countries.get("Indiaa"))
}
}
[/sourcecode]
The output of this method is
India Some(1)
Indiaa None
As you would notice, the value Some is a a wrapper around the actual value which is 1. For the other case however, since there is no value ( or null as in Java) an object of the type None is returned. So we can always expect an object as a return type and not a keyword.
How do you get the actual values? Let us look at the modified code and the convenience methods in the new code
[sourcecode language=”scala”]
object MapTester{
def main(args: Array[String]) {
createMap()
}
def createMap(){
val countries = Map("India"->"1", "Pakistan"->"3", "SriLanka"->"2")
println("India " + countries.get("India").get)
println("Indiaa "+countries.get("Indiaa").getOrElse("default"))
}
}
[/sourcecode]
As you would notice here, the output is
India 1
Indiaa default
What we have done here is that we call get on the Some object to get its actual value. Likewise, we do a getOrElse(“”) method on the object to get either the actual value or return a default value just in case the object is None. We could have used the getOrElse in the first statement too and the result would have been the same since countries.get(“India”) would return a Some.
Thus, whenever there is a method which you custom code which has the possibility of returning a null in the Java, nil in Ruby sense then Scala strongly recommends using an Option type to remove ambiguity and keep the code clean.
regarding the null causing snafus, a little known pattern(in my experience) is the “null” object pattern: http://en.wikipedia.org/wiki/Null_Object_pattern
I’m not sure why it is not more widely known, maybe because it isn’t there in the GoF book.