Scala: flatMap

Learn
2 min readJan 16, 2022

--

The world has been flattened there. flatMap kind of works the same, it breaks the shell and gives you the egg, the wrapper is removed and you get the chocolate. If you need to map and then flatten, use flatMap instead.

Imagine you are collecting easter eggs and flattening them, some of these easter eggs would have chocolates in them, and some would be empty. When you flatten these easter eggs, two things happen.
- The shells get destroyed and the chocolates take their place.
- The empty shells get obliviated completed.
For example, if you had ten easter eggs, and you had four of those empty and one chocolate each in the remaining six eggs, on doing the flatten exercise on the ten shells, you get six chocolates and that is it. You don’t know which eggs were empty and whether all six chocolates in one shell or not. But then, chocolates is all you care about anyway!

In programming terms, all that I mean is that the None s would get filtered out, and the Some s would get unwrapped on flattening.

Let us look at a flatten example closely first.

def singleDigitTwice (n : Int) : Option[Int] = {
if(n < 10) Some(2 * n)
else None
}
(0 until 20)
.toList
.map(singleDigitTwice)
.foreach(println)
println("Output after flattening")(0 until 20)
.toList
.map(singleDigitTwice)
.flatten
.foreach(println)

The output is as below, the wrappers can seem very noisy when all you care for is the actual output.

Some(0)
Some(2)
Some(4)
Some(6)
Some(8)
Some(10)
Some(12)
Some(14)
Some(16)
Some(18)
None
None
None
None
None
None
None
None
None
None
Output after flattening
0
2
4
6
8
10
12
14
16
18

The flattening happens only for the outermost wrapper when there are nested wrappers as demonstrated below.

List(Some(1), Some(2)).flatten.foreach(println)
println("---Nested wrappers two -----")
List(Some(Some(1)), Some(Some(2))).flatten.foreach(println)
println("-- Nested wrappers three ---")
List(Some(Some(Some(1))), Some(Some(Some(2)))).flatten.foreach(println)
1
2
---Nested wrappers two -----
Some(1)
Some(2)
-- Nested wrappers three ---
Some(Some(1))
Some(Some(2))

Now that we have seen the value of flattening, let us get to flatMap which is a shortcut for map followed by flatten .

The same output with one less method call — by calling flatMap directly.

def singleDigitTwice (n : Int) : Option[Int] = {
if(n < 10) Some(2 * n)
else None
}
println("Use flatMap")(0 until 20)
.toList
.flatMap(singleDigitTwice)
.foreach(println)
Use flatMap
0
2
4
6
8
10
12
14
16
18

I had the impression that flatMap takes a wrapper as argument and flattens it.

Option(2).flatMap(println)
* DOES NOT WORK

That is not the abstraction, flatMap is not about taking a wrapper and flattening. It does two actions — mapping and then flattening. It is not the same as unwrapping a wrapper.

When you need to use map and then flatten, use flatMap. Also, do not think of a flatMap when you need to unwrap a container.

--

--

Learn
Learn

Written by Learn

On a continuing learning journey..

No responses yet