Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

Scala Options

I tried to explain Options in Scala in a lightening talk this week and I don’t think I did a particular good job at this. I started by talking about how you might use Options instead of doing null checks in a first step towards a more idiomatic way of using Scala, but perhaps I should have skipped that and gone straight to the interesting parts. So while my presentation is available with those comments, here I will skip the first half of that and get to it.

An Option represents an optional value, it either contains a value, or it does not. In Scala the terms used are that an option has Some of X, or None. While this does give you some nice wrap around doing Null checks, it doesn’t buy you much more than that until you consider that an Option can be thought about as a sequence of zero or one elements, and that you can use functions on an Option that you would do on a list. This gives you access to map, filter, flat map and all the others.

This in turn opens up the world of transformations and list comprehensions. Now we’re going into idiomatic Scala. One of the most used elements in Scala that I’ve seen is taking one object and transforming that into another. When transformations are done a few at a time, you can quickly eliminate a lot of plumbing code through chaining calls to get to what you need. You can do this safely using Options as each step in the chain returns an Option, and the first step in the chain to return a None will evaluate the whole expression as None.

This example has an option of a person, transforms that into an option of department and then into an option of the department name as a string. If at any time the object is None, the whole statement will return None. If it gets through to the department name, it will return a Some of String (Some[String]). The underscore in the example is the value within the Option after the map has been applied. This can be assigned to a locally scoped variable too, but for conciseness, I’m using the underscore.

val personOption = Some(person)

val departmentName1 = personOption.flatMap { person => person.department } map { department => }

val departmentName2 = personOption flatMap { _ department } map { _ name }

Options have functions that allow you to retrieve the value, retrieve the value with a given default if the value is None, or check to see if the object is defined. To get the name of the department, we can do:

val deptName = departmentName1 getOrElse (“No department”)

That’s cool, but we can go one further with list comprehension. This is where we turn a list into another list. Remember earlier we said an Option can be considered an sequence of zero or more elements, so we can apply list comprehension to an option and return an option. Each line here will assign from right to left, and if at any step something on the right is None, the expression will be None. We can also apply conditions into the comprehension, so that if the name of the department is engineering the whole expression returns None.

val departmentName3 = for {
    person <- personOption
    department <- person.department
} yield

Both of these method can be applied to lists as well as options, so that if personOption was actually a list of people, the result would be a list of department names. Here we apply the same code to a list to get all the non-engineering department names.

val person2 = Person(Some(Department("Design")))

val people = List(person, person2)

val nonEngineeringDepartments = for {
    person <- people
    department <- person.department if != "Engineering"
} yield

This train of thought started when I wanted to do something in Ruby that I knew how to do in Scala and it turned into me trying to explain some of these concepts in Scala. I’m still fairly new to Ruby, and I’m not saying ‘I wish I could do this in Ruby’, more ‘I wish I knew if I could do this in Ruby’.

More code is available in this Gist:

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *