Scala: flatMap

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.

--

--

--

On a continuing learning journey..

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Chapter 12 Preparing for Production

Sweetie Sundae #4

Evanesco mainnet is coming!

Great IOTA community: It’s not just the big applications that make IOTA noteworthy

Chapter 2 Create Stateful Elm Applications

Legacy Code: definition, recommendations & books

Exporting your Trello-Boards with Python

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Learn

Learn

On a continuing learning journey..

More from Medium

[Scala] Implicit Parameters

Scala: for-comprehension contexts do not mix

Type Classes in Scala 2

Polymorphic functions in Scala