Best Practices for nested Scala Option fields?

scala, scala-option

Solution

In this case, the most readable solution out of the box (that is, without writing helper methods) would argueably be to chain calls to `Option.flatMap`:

objectA flatMap (_.attrB) flatMap (_.attrC.headOption) flatMap (_.attrD)

By using `flatMap`, if any of the option in the chain is `None`, you'll end up with `None` at the end (no exception unlike with `get` which will blow when called on `None`).

By example:

case class C(attrD: Option[String])
case class B(attrC: List[C])
case class A(attrB: Option[B])

val objectA = Some(A(Some(B(List(C(Some("foo")), C(Some("bar")))))))

// returns Some(foo)
objectA flatMap (_.attrB) flatMap (_.attrC.headOption) flatMap (_.attrD) 

val objectA2 = Some(A(Some(B(List()))))

// returns None
objectA2 flatMap (_.attrB) flatMap (_.attrC.headOption) flatMap (_.attrD)

You could also use for comprehensions instead of `flatMap` (for comprehension being desugared to chains of `flatMap`/`map`), but in this case it will actually be less readable (the opposite is usually true) because on each step you'll have to introduce a binding and then reference that on the next step:

for ( a <- objectA; b <- a.attrB; c <- b.attrC.headOption; d <- c.attrD ) yield d

Another solution, if you're willing to use ScalaZ, is to use `>>=` in place of `flatMap`, which makes it somewhat shorter:

val objectA = Option(A(Some(B(List(C(Some("foo")), C(Some("bar")))))))
// returns Some(foo)
objectA >>= (_.attrB) >>= (_.attrC.headOption) >>= (_.attrD)

This is really exactly the same as using `flatMap`, only shorter.

Problem

I've got a number of nested objects, all wrapped in a Scala Option type. Elsewhere in my project I'm having to call an attribute that is embedded some 5 levels deep (some of which are Lists), each time making a call to `.get`. This way I end up with something that looks like the following: ``` objectA.get.attrB.get.attrC.get(0).attrD.get ``` Other than the series of `.get` calls (which I'm not sure is ideal), I'm not implementing much error handling this way and should any of the attributes be empty then the whole thing falls apart. Given the nested calls, if I were to limit this to a one-liner as above, I would also only be able to use `.getOrElse` once at the end. Are there any suggested ways of working with Option types in Scala?

Original source