I can't figure out how the Scala compiler figures out how to use flatMap
with a sequence of Option
s.
If I use a flatMap
on a sequence of sequences:
println(Seq(Seq(1), Seq()).flatMap(a => a)) // List(1)
it will concatenate all nested sequences
The same happens if I use it with a sequence of Option
s:
println(Seq(Some(1), None).flatMap(a => a)) // List(1)
So the flatMap
treats Option
as a collection in this case. The question is why does this work? The flatMap
has the following definition:
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That
Meaning that it expects a function that returns an instance of GenTraversableOnce
, but Option
does not inherit GenTraversableOnce
. It only inherits Product
and Serializable
, and Product
inherits Equals
.
How does Scala compiler can use the flatMap
on the sequence of Option
s in this case?
In Scala, flatMap() method is identical to the map() method, but the only difference is that in flatMap the inner grouping of an item is removed and a sequence is generated. It can be defined as a blend of map method and flatten method.
The flatMap() method is similar to the map() method, but the only difference is that in flatMap, the inner grouping of an item is removed and a sequence is generated. The flatMap method acts as a shorthand to map a collection and then immediately flatten it.
Using flatMap() is useful when you want to add and remove items during a map() , as it can map many to many items by handling each input item separately, versus map() itself that is always one-to-one. This means the resulting array can grow during the mapping, and it will be flattened afterward.
Scala Seq is a trait to represent immutable sequences. This structure provides index based access and various utility methods to find elements, their occurences and subsequences. A Seq maintains the insertion order.
Your observation is right. In this case, if the compiler can't match the type, it looks for an implicit conversion and finds one in Option
's companion object:
import scala.language.implicitConversions
/**
An implicit conversion that converts an option to an iterable value
*/
implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList
This makes it possible to treat Option
s as Iterable
s.
Also, your code can be simplified using flatten
:
Seq(Some(1), None).flatten
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With