It’s like that time you played basketball in the living room. You knew you should never have done it. But it was just so tempting! And how did that work out for you? Broken lamp? Hole in the wall? And, if you grew up in a house like mine, a tanned hide to follow. You could have avoided it all: the property damage, the wounded pride, the tender backside.
That’s what playing with null is like. You know you shouldn’t, but it’s just so easy! Then you get burned in the end.
The Problem with Null
The problem with null is that it can crop up anywhere an object can. Consider a function that returns a string. This is always OK, right?
val foo: () => String = // ... val len = foo().length // No worries?
It certainly is in this case:
val foo: () => String = () => "foo" val len = foo().length // len: Int = 3
But what about this?
val foo: () => String = () => null val len = foo().length // java.lang.NullPointerException !!!
Yeah, not so much. And the problem is that the compiler cannot help us: null is a perfectly legal return value.
We need better semantics! A return type of String ought to guarantee me that I get a String. An empty string would be fine; it just needs to be a String!
Even the guy who invented the concept of null has regretted it:
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler.
But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
Sir Charles Antony Richard “Tony” Hoare
Turing Award Winner, Inventor of the Quicksort
Null References: The Billion Dollar Mistake (2009)
Fine! All this lamenting that null is a bad idea is great, but don’t you need a way to represent the idea that sometimes a function may not return a result, or at least, not what you would consider a valid result? That’s what Java maps do: If you call Map.get(key), and that map does not contain an entry for key, you get null. Of course, with most maps, null is a legal value, so you don’t know for certain whether null indicates whether the key was not found or the coder explicitly associated null with that key.
There’s got to be a better way!
Option to the Rescue
When you need to represent the idea that a function may not return a result, use Scala’s Option. You can think of an Option as a bucket (pronounced BUCK-et, not boo-KAY):

When a function returns an Option[T], it may contain a value of type T; it may not. You don’t know until you look into it. It’s Schrödinger’s cat! If the Option is empty, we call it None. If it is full, we call it Some.
The advantage of using Option is that now the compiler can help you out. You cannot assign an Option[T] to a variable of type T. Take this example using List.find:
val opt = (1 to 4).toList.find(_ > 5) val n : int = opt // error: not found: type int // val n : int = opt
So then, you cannot forget and accidentally assign a null, only to have it bite you later. The compiler reminds you that you need to test the result before trying to use it:
val ns = (1 to 4).toList
val none = ns.find(_ > 5)
if (none.isEmpty) {
println("None found greater than 5")
} else {
println(s"Found one greater than 5: ${none.get}")
}
// None found greater than 5
val some = ns.find(_ < 5)
if (some.isEmpty) {
println("None found less than 5")
} else {
println(s"Found one less than 5: ${some.get}")
}
// Found one less than 5: 1
Of course, you can override the safeguard, but at least then, you cannot claim ignorance:
val ns = (1 to 4).toList
val none = ns.find(_ > 5)
println(s"Found one greater than 5: ${none.get}")
// java.util.NoSuchElementException: None.get !!!
Next week, we will look at Option some more to see how we can use it in a more functional fashion.

![The foldLeft operation produces the product of the list of integers [5,3,6] by starting with 1 (because 1 times x is always x), multiplying 1 and 5 to get 5, multiplying 5 and 3 to get fifteen, and finally multiplying 15 and 6 to get a final product of 90.](https://bradcollins.com/wp-content/uploads/2015/05/scala-fold-int-product-300x282.png)
![The foldLeft operation can concatenate a list of strings together with a separator, but this figure illustrates how the desired result is a little more complicated than it is with reduce. Taking a list of strings ["do", "mi", "sol"], a starting value of an empty string, and a binary operation that concatenates two strings together with a hyphen in the middle, you end up with an extra hyphen at the front of the resulting string. That is because the first application of the binary operation concatenates the empty string with a hyphen and "do". In a join operation, you usually only want the separator between values, so using foldLeft requires some additional checking.](https://bradcollins.com/wp-content/uploads/2015/05/scala-fold-str-concat-1024x587.png)
![Taking a list of [2,5,3,6], reduce multiplies 2 and 5 to produce 10, then 10 and 3 to produce 30, and finally 30 and 6 to get the final result of 180.](https://bradcollins.com/wp-content/uploads/2015/05/scala-reduce-int-product-300x275.png)
![Taking a list of strings ["do","mi","sol","do"], reduce combines "do" and "mi" to produce "do-mi", and then combines "do-mi" and "sol" to produce "do-mi-sol", and finally "do-mi-sol" and "do" to produce the final result of "do-mi-sol-do"](https://bradcollins.com/wp-content/uploads/2015/05/scala-reduce-string-concat-1024x554.png)


