Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala - Difference between map and flatMap [duplicate]

Can anyone teach me property use cases of map and flatMap?

In Option case, I know these two methods have each signature, def map(A => B): Option[B] and def flatMap(A => Option[B]): Option[B].

So, I can get some value by two ways:

scala> val a = Some(1).map(_ + 2)
a: Option[Int] = Some(3)

scala> val a2 = Some(1).flatMap(n => Some(n + 2))
a2: Option[Int] = Some(3)

When I write a method: def plusTwo(n: Int), is there any difference between

def plusTwo(n: Int): Int = n + 2
Some(1).map(plusTwo)

and

def plusTwo(n: Int): Option[Int] = Some(n + 2)
Some(1).flatMap(plusTwo)

flatMap can convert to for-comprehension, and is it better that almost all methods return value Option wrapped?

like image 295
ryochanuedasan Avatar asked Aug 18 '26 01:08

ryochanuedasan


2 Answers

Let's say you have a List:

val names = List("Benny", "Danna", "Tal")
names: List[String] = List(Benny, Danna, Tal)

Now let's go with your example. Say we have a function that returns an Option:

def f(name: String) = if (name contains "nn") Some(name) else None

The map function works by applying a function to each element in the list:

names.map(name => f(name))
List[Option[String]] = List(Some(Benny), Some(Danna), None)

In the other hand, flatMap applies a function that returns a sequence for each element in the list, and flattens the results into the original list

names.flatMap(name => f(name))
List[String] = List(Benny, Danna)

As you can see, the flatMap removed the Some/None layer and kept only the original list.

like image 92
Weknin Avatar answered Aug 20 '26 15:08

Weknin


Your function plusTwo returns valid results for all input since you can add 2 to any Int.

There is no need to define that it returns Option[Int] because None value is never returned. That's why for such functions you use Option.map

But not all functions have meaningful result for every input. For example if your function divide some number by function parameter then it makes no sense to pass zero to that function.

Let's say we have a function:

def divideTenBy(a: Int): Double

When you invoke it with zero then ArithmeticException is thrown. Then you have to remember to catch this exception so it's better to make our function less error prone.

def divideTenBy(a: Int): Option[Double] = if (a == 0) None else Some(10 / a)

With such functions you can use flatMap since you can have 'None' value in optional (left operand) or given function can return None.

Now you can safely map this function on any value:

scala> None.flatMap(divideTenBy)
res9: Option[Double] = None

scala> Some(2).flatMap(divideTenBy)
res10: Option[Double] = Some(5.0)

scala> Some(0).flatMap(divideTenBy)
res11: Option[Double] = None
like image 21
Eanlr Avatar answered Aug 20 '26 16:08

Eanlr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!