Scala: Processing Option-wrapped Collections
In Scala, there are a lot of cool things - too many to list. Among them is something borrowed from Haskell; the Maybe, spelt Option in Scala, which itself is based on the concept of computing via monads.
The reason why Option
is awesome is that, if used properly, it largely frees the programmer from having to worry about various variables being in states of nothingness (Nil, null, etc). Without fail, every programmer has at one point or another written things like thing.nil? ? do_nothing : do_something
…. all over the place. The point (in my mind, at least) of Option
is to free us from having to do this in as many places as possible.
Many libraries in Scala, such as Scala-Redis are made with the assumption that the programmer knows how to deal with Option
and return results wrapped in either Some[List[T]]
or None
. That said, how to work with these types of results is not exactly straight forward for someone coming from other languages that don’t have such constructs, so I’ve written down some of my thoughts.
As an example, let’s try tackling the issue of how to use a result like the one that comes from Scala-Redis: Some[List[T]]
.
To keep things simple, assume we have a val maybeList = Some(List(1,2,3))
and we want to increment each member of the list inside the Option
, and want to return anotherOption
with the incremented list inside. While we could potentially do pattern matching to check if the Option
is a None
, we would prefer to take advantage of the patterns afforded to us by the fact that we’re dealing with an Option
. This means using map
, flatMap
and for
.
Based on what official Scala documentation on Options tells us, we have
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
There are two versions that we can choose from; one using map
and another using for
. In essense, they are the same, because for-comprehensions boil down to appropriate map
and flatMap
methods anyway. This also means that sometimes you may get funky errors with type mismatch errors, for which a good rule of thumb is to remember that for comprehensions will try to return the type of the collection of the first generator
Using the code above, we can do:
1 2 3 4 5 6 7 |
|
The fact that calling incrementMaybeList
with maybeList
worked should not be surprising, but notice how maybeListNone
didn’t cause the function to throw up. This is because calling methods like map
or using for-comprehnsion on Option
s that are None
immediately return None instead of proceeding to run internal logic. No need to write if/else guards !
By building and using functions like incrementMaybeList
, where an Option
is processed and an Option
is returned throughout the code, one can stop worrying about Nothingness (for the most part), because they can be chained together.
1 2 |
|
When the time comes to actually do something with those Option
-wrapped results without returning another value, once again, its time to break out for-comprehensions.
1 2 3 4 5 6 7 8 9 10 11 |
|
Conclusion
Option
s free the programmer from worrying about Nothingness and thus from writing tons of boilerplate nothingness checks in our code. This blog post talks about a simplish, but applicable example on how to deal with Option
in Scala.