I learn Scala for some time and can't clearly understand the usage of Option. It helps me to avoid null checks when I chain functions (according to docs). That's clear for me :)

Next I see that Option can be kind of indicator for developer that null value is possible here and it must be handled. Is it true? If yes should I use Option whereever it's possible? For example

class Racer {
val car = new Car()
}

I have Racer class and I'm sure that car field can't be null (because it's constant and get a value when I create Racer instance). No need for Option here.

class Racer {
var car = new Car()
}

Here I make it so that the car can change. And it's possible for someone to assign null to car. Should I use Option here? If yes I notice that all my class fields are candidates for Option. And my code looks like this

4 Answers
4

You should avoid null as much as possible in Scala. It really only exists for interoperability with Java. So, instead of null, use Option whenever it's possible that a function or method can return "no value", or when it's logically valid for a member variable to have "no value".

With regard to your Racer example: Is a Racer really valid if it doesn't have a car, currentRace and team? If not, then you shouldn't make those member variables options. Don't just make them options because it's theoretically possible to assign them to null; do it only if logically you consider it a valid Racer object if any of those member variables has no value.

In other words, it's best to pretend as if null doesn't exist. The use of null in Scala code is a code smell.

Also, if you want to program in the functional style, you should avoid mutable data as much as possible, which means: avoid the use of var, use val instead, use immutable collections and make your own classes immutable as much as possible.

In addition to "pretend[ing] as if null doesn't exist", if you have to deal with Java code that gives you foo which might be null, you can use Option(foo), which will turn null into None, and anything else into Some(blah).
–
Dan BurtonMar 14 '12 at 17:35

While Option can makes your class definition look verbose, the alternative is to not know when you need to test whether a variable is defined. I think that in your example, if your class were immutable (all the fields were vals), you would not need so many Options.

For your method foo, if you return null, you need to document it and the client needs to read that documentation. Then the client will write a bunch of code like:

val result = foo(x)
if (result != null) {
println(result)
}

If instead you define foo to return an Option[Result], the type system forces the client to handle the possibility of an undefined result. They also have the full power of the collections classes.

result foreach println

An additional advantage of using the collections method with an Option instead of testing for null is that if your method is extended to a multi-element collection (such as a List), you might not need to change your code at all. For example, you might initially assume your Racer can only have a single crew, so you define val crew: Option[Crew] and you might test if the crew is older than 30 with crew.forall(_.age > 30).getOrElse(false). Now if you changed the definition to val crew: List[Crew] your old code would still compile and now you would check if all of your crew members are over 30.

Sometimes you need to deal with null because libraries you are using may return it. For example, when you get a resource, you might get a null result. Fortunately, it is easy to defensively wrap results so they are transformed into an option.

val resource = Option(this.getClass.getResource("foo"))

If getResource returned null then resource equals None, and otherwise it is a Some[URL]. Cool!

Unfortunately, Option is likely to have some overhead because it involves an extra object creation. However, that overhead is minimal compared to a null pointer exception!

To make a class immutable do you suggest to make a copy of an instance every time I want to change it? Like Nicolas told.
–
SotericMar 15 '12 at 2:40

1

Yes, but this depends somewhat on how you are using the object. If you have an object with many fields that you change frequently, immutable might not make sense. However, you can often design your code differently so you are performing less mutation. If you need mutation, you can hide the mutability through a trait (for example, List has a mutable field--you just can't access it).
–
schmmdMar 15 '12 at 2:45

The idea behind Options is to get rid off null, so yes, you should use them instead of returning "null or a value". That's also why, if you want to model optional fields (0..1 relationship with other objects), using Option is definitely a good thing.

The little drawback is that it renders declaration of class with a lot of optional field a bit verbose, as you mentionned.

One more thing, in scala, you are encouraged to use "immutable objects", so in your example, the fields should be some vals. ;)

In case I use val how can I change the value? What if I want a new car for my racer?
–
SotericMar 14 '12 at 10:25

3

The idea is to build a new object when a event like a new car occurs: class Racer(name: String, car: Option[Car]) {def receiveANewCar(c: Car) = new Racer(name, Some(c)); def brokeHisCar = new Racer(name, None)}
–
NicolasMar 14 '12 at 10:55