问题
For example,
Vector(Some(1), Some(2), Some(3), None).flatMap{
n => n
}
produces a Vector(1, 2, 3) instead of giving an error. As I have seen in other languages, flatMap is used when you have a mapper function that produces nesting so I would expect this to be a valid flatMap:
Vector(1, 2, 3).flatMap{
eachNum => Vector(eachNum)
}
My mapper function produces a Vector which would cause nesting (i.e. Vector(Vector(1), Vector(2), Vector(3), Vector(4))) if I used a map due to the container wrapping. However, flatMap will remove this nesting and flatten it. This makes sense when there is nesting of two identical monads.
However, I do not understand how using a flatMap with a mapper function that returns an Option makes a Vector[Option[Int]] become a Vector[Int]. Is there some sort of transformation going on (I have never seen this before), could someone explain and perhaps point me to some resources?
Thank you very much
回答1:
we can use reify to see what is going on:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> val v = Vector(Some(1), Some(2), Some(3), None)
v: scala.collection.immutable.Vector[Option[Int]] = Vector(Some(1), Some(2), Some(3), None)
scala> reify { v.flatMap(x => x) }
res0: reflect.runtime.universe.Expr[scala.collection.immutable.Vector[Int]] =
Expr[scala.collection.immutable.Vector[Int]]($read.v.flatMap(((x) =>
Option.option2Iterable(x)))(Vector.canBuildFrom))
This is showing us that it is using the option2Iterable conversion to convert the Option to Iterable, and Iterable is a subtype of the GenTraversableOnce type that flatMap is expecting.
回答2:
The function f passed within the flatMap here:
Vector(Some(1), Some(2), Some(3), None).flatMap{
n => n
}
Is a function A => GenTraversableOnce[B] as described in the flatMap implementation:
def flatMap[B, That](f : scala.Function1[A, GenTraversableOnce[B]])
(implicit bf : CanBuildFrom[Repr, B, That])
: That = ???
The function implemented in your example n => n is:
(n: Option[Int]) => n
Where A is Option[Int] and B is Int.
Because CanBuildFrom is defined as trait CanBuildFrom[-From, -Elem, +To]:
FromisRepr, and in this caseVectorElemisBsoInt
The result of flatMap is therefore Vector[Int]
来源:https://stackoverflow.com/questions/34735364/why-is-flatmap-on-a-vectoroptionint-whose-mapper-function-result-is-not-a-ve