Ok, to start with, the recommendation is to use None instead of null. Ideally if in Scala code, we end up getting a NPE then that is sin! Well at least at Knoldus 🙂
null in Java is used as a placeholder for denoting no value or a non-fatal error situation. It is widely accepted as a Billion dollar mistake of Java. The way to work around it is to have a NullObjectPattern which is present as a pattern in variety of languages and which people seldom use.
Scala is smart. It has an option which is a container. Now the container can either have something or it can be empty. Most of the times developers working in Scala use it in either of the two situations
First, when they are working with a Java API which possibly returns null. Since you would not want to work with null in Scala then you would wrap the Java API call in an Option. Something like this
If you would notice, most of the developers coming from the Java world would be writing code like this.
However, Option provides us with lot of cool ways to implement our logic. For starters, instead of checking == you could instead do
Ok, i see you throwing a stone at me. What is the big deal here? You could also do a getOrElse
Still, what is the big deal? Well, we have just started!
One of the cool feature of option is that it can be treated like a collection. What? Yes, you can call methods like map, flatMap, foreach and use it in for comprehensions. Let us see how that makes things easier for us.
for
We want to execute a portion of the logic only if we have got a value in the Option container. There is “a” way and then a better way to do it. See the code below
Now the for comprehension would evaluate only if res is not an empty box i.e. it has some value. But, what if there are multiple options that we want to compose together. For example the following code block
What do you think is going to be the output of this code block? If you answered None you are correct. And now?
The result in this case would be Some(109Hi)
map
Let us look at a good case of using a map now. Look at the code below
What would happen to this code if a was None. It would throw a java.util.NoSuchElementException: None.get.
Another way of working with this code is to map over it like a collection.
map would result in a value since it would be evaluated as an expression. If you would like to have normal looping for a side effect operation, you could use a foreach instead. Example
similarly you can flatMap on an option.
filter
Just like collections, it is easy to filter on an option if it has a value
As you would expect by now, the empty box does not get evaluated.
chaining
We can chain several options together just like PartialFunction with orElse
more
Then there are other things to try like
Thus as you would have noticed that Option is quite powerful. It is more than just checking for null or None and writing your business logic around it. Option is a monad in the loose sense since it supports composition by flatMap. It has the ability to be used in for comprehension and provides collection functions which makes it quite useful to write well meaning code.
The worksheet gist for all the above code is present here. Have fun!
Satendra suggests 2 more things
1) What if you have a scenario like if then SOMETHING else SOMETHING_ELSE . The way to deal that with an option would be like
val b = Some(1)
b map (x=>x+1) getOrElse(9)
This is ok, but the problem with getOrElse is that it would not complain about the datatype. So if instead of the above, we had
val b = Some(1)
b map (x=>x+1) getOrElse(“9”)
That would continue to work.
A better way is to use fold instead
b.fold(1)(x=>x+1) where (1) is the else state and (x=>x+1) is the function to be called when we get a Some. This would complain when we change the datatype
b.fold(“1”)(x=>x+1) // This would not compile