If you check your compiled code, you see that for yield
is desugered to flatMap
equivalent to (1 to 3).flatMap(a => Some(2).map(b => (a, b)))
which is valid.
scalac -Xprint:parser Test.scala
[[syntax trees at end of parser]] // Test.scala
package <empty> {
object T extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
def main(args: Array[String]): Unit = {
val x = 1.to(3).flatMap(((a) => Some(2).map(((b) => scala.Tuple2(a, b)))));
println(x)
}
}
}
So, the inner computation is Some[Tuple2]
wrapped in a outer List
/ Vector
context that's why you are able to flatMap
to outer context as flatMap
def is
final override def flatMap[B](f: Option[Int] => scala.collection.IterableOnce[B]): List[B]
While in second example,
Some(2).flatMap(b => List(1, 2, 3).map(a => (a, b)))
your are asking to .flatMap
on Some
context while the inner context being List
/ or Vector
. So it can not flatMap
.
In summary what should work for flatMap
is,
| Outer context | Inner context | Result | example
|
|---------------|---------------|-----------|----------------------------------------
| List | List[a] | List[a] | List(List(1, 2), List(2)).flatMap(a => a)
| List | Option[a] | List[a] | List(Some(1), Some(2)).flatMap(a => a)
| Option | Option[a] | Option[a] | Some(1).flatMap(a => Some(a))