Scala Saturday – The flatMap Method

In a previous Scala Saturday post, we looked at the map method. As a quick review, map lets you take a collection of elements, calculate a new value from each source element, and create a new collection containing those new values. The mapping function has the following signature:

A => B

In other words, the function takes a single value of type A and returns a single value of type B.

But what if you have a mapping function with this signature?

A => List[B]

In other words, this function does not take one value and produce one value. Rather it takes one value and produces multiple values. What if you’re OK with that, but you just need to take those many values returned from each mapping and smash them all together into one list?

From Side to Side

Most of the guys in legendary progressive rock band Yes didn’t have just one job on their Close to the Edge album. They performed multiple duties. So let’s create a Musician case class to represent a musician and the list of instruments he plays on the album:

case class Musician(
  name: String,
  instruments: List[String])

Now you can create a list of musicians:

val yes = List(
  Musician("Jon Anderson", List("vocals")),
  Musician(
    "Steve Howe",
    List("electric guitars", "acoustic guitars",
      "vocals")
  ),
  Musician(
    "Chris Squire",
    List("bass guitar", "acoustic guitars",
      "vocals")
  ),
  Musician(
    "Rick Wakeman",
    List("Hammond organ", "Minimoog",
      "Mellotron", "grand piano",
      "RMI 368 Electra-Piano and Harpsichord",
      "pipe organ at St. Giles, Cripplegate church")
  ),
  Musician(
    "Bill Bruford",
    List("drums", "percussion")
  )
)

Maybe you want one long list of every instrument the fellows in Yes used on the album. You just have to map each musician to his list of instruments, and then concatenate those lists together:

Illustrates mapping a list of musicians (jon, steve, chris, rick, nill) to a list of lists of the instruments that each musician plays ((vocals), (electric guitars, acoustic guitars), (bass guitar, vocals), (Hammond organ, Minimoog, ...), (drums, percussion)) and then a flattening of those nested lists into one long list
Collecting Musicians’ Instruments into One Long List

You could do this with two functions you’ve read about already on Scala Saturdays: map and concat:

val instruments = yes.map(_.instruments).flatten
// instruments: List[String] =
//   List(vocals, electric guitars, acoustic guitars,
//     vocals, bass guitar, ...)

The Total Mass

What if there were a function that could do both of those things—perform the transformation and the concatenation all in one? Turns out that there is: flatMap!

val instruments = yes flatMap (_.instruments)
// instruments: List[String] =
//   List(vocals, electric guitars, acoustic guitars,
//     vocals, bass guitar, ...)

How ’bout that? The very same results all in one function!

So then, flatMap performs a map and a flatten all in one function call.

You’ve seen flatMap examples here only in terms of lists, but the Scala’s other collections define the flatMap method, too:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.