Maps or For Comprehension?

Maps are a powerful tool in Scala, allowing you to apply a function to each item in a collection; however they sometimes can be a bit difficult to understand, especially for programmers who are new to Scala or functional programming in general.

As mentioned previously, one of the strength of Scala lies in the fact that it allows different solutions to the same problem. For example, given we have a list of Strings and want to transform each member to uppercase:

val listOfItems: List[String] = List("first", "second", "third")

We can simply do this using maps:

val upperCaseListOfItems: List[String] = listOfItems map (_.toUpperCase)

Which would result in:

upperCaseListOfItems: List[String] = List(FIRST, SECOND, THIRD)

However, we could have as easily used for comprehension:

val upperCaseListOfItems: List[String] = for {
  item <- listOfItems
} yield item.toUpperCase

Maps might be more functional, but I have always found for comprehensions easier to use and understand. It basically depends on how you learnt about Scala and your background, and which of these two methods you learnt about first!

I have always believed that what matters a lot is that the code is readable to other engineers, and for comps certainly achieve that.


Maps vs. Pattern Matching

One of the things I like about Scala is that it allows you to do the same thing, many different ways. Because of this, there is always the challenge of making the code more efficient; hopefully not at the expense of readability.

Take for example the concept of pattern matching in Scala. If we have:

case class Availability(startDate: Option[String])

val availability = Availability(Some("2016-05-06T09:00:00"))

And want to write a method which retrieves the startDate from an optional Availability, short of using if/else conditions, pattern matching would be the easiest way:

def getStartDate(available: Option[Availability]): Option[String] = available match {
  case Some(x) => x.startDate
  case None => None

Then if we call:


We would get:

res0: Option[String] = Some(2016-05-06T09:00:00)

But this is not the most efficient way, and there is a much simpler way of getting the same result using maps:

def getStartDate(available: Option[Availability]): Option[String] = 
  available map (_.startDate) getOrElse None

Which can even be further simplified to:

def getStartDate(available: Option[Availability]): Option[String] = 
  available flatMap (_.startDate)

Personally I prefer the solution with flatMap, but because of the flexibility that Scala provides, you can always choose any of these options to get the same result.