Nirmalya Nirmalya - 6 days ago 4
Scala Question

Correct interpretation of Scala Map's flatmap expression

I am scratching my head vigorously, to understand the logic that produces the value out of a flatMap() operation:

val ys = Map("a" -> List(1 -> 11,1 -> 111), "b" -> List(2 -> 22,2 -> 222)).flatMap(e => {
| println("e =" + e)
| (e._2)
| })
e =(a,List((1,11), (1,111)))
e =(b,List((2,22), (2,222)))
ys: scala.collection.immutable.Map[Int,Int] = Map(1 -> 111, 2 -> 222)


The println clearly shows that flatMap is taking in one entry out of the input Map. So, e._2 is a List of Pairs. I can't figure out what exactly happens after that!

I am missing a very important and subtle step somewhere. Please enlighten me.

Answer

It can be thought of as:

First we map:

val a = Map("a" -> List(1 -> 11,1 -> 111), "b" -> List(2 -> 22,2 -> 222)).map(e => e._2) 
// List(List((1, 11), (1, 111)), List((2, 22), (2, 222)))

Then we flatten:

val b = a.flatten
// List((1, 11), (1, 111), (2, 22), (2, 222))

Then we convert back to a map:

b.toMap
// Map(1 -> 111, 2 -> 222)

Since a map cannot have 2 values for 1 key, the value is overwritten.


Really whats going on is that the flatMap is being converted into a loop like so:

for (x <- m0) b ++= f(x)

where:

  • m0 is our original map

  • b is a collection builder that has to build a Map, aka, MapBuilder

  • f is our function being passed into the flatMap (it returns a List[(Int, Int)])

  • x is an element in our original map

The ++= function takes the list we got from calling f(x), and calls += on every element, to add it to our map. For a Map, += just calls the original + operator for a Map, which updates the value if the key already exists.

Finally we call result on our builder which just returns us our Map.