I just looked at the List.flatMap declaration and was kind of surprised by this.
final override def flatMap[B, That](f: A => GenTraversableOnce[B])
                 (implicit bf: CanBuildFrom[List[A], B, That]): That
Where object List defines:
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, List[A]] =
    ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
So, if we invoke flatMap on a List we will get the List and I don't see any point in That type if it will always be deduced to List[B] (because of the implicit).
So, if we invoke
flatMapon aList[A]we will get theList[A]and I don't see any point inThattype if it will always be deduced toList[B]
One thing you're missing is that flatMap isn't actually defined on List[+A]. It is inherited from TraversableLike, which is a trait used by most of Scalas collections. Each of them can supply the implicit CanBuildFrom which may be overridden to supply a different resulting collection.
If you want a little taste of what you can do with a custom CanBuildFrom:
scala> :pa
// Entering paste mode (ctrl-D to finish)
import scala.collection.generic.CanBuildFrom
import scala.collection.immutable._
import scala.collection.mutable
import scala.{List, Vector}
implicit val listToVectorCBF = new CanBuildFrom[List[Int], Int, Vector[Int]] {
  override def apply(from: List[Int]): mutable.Builder[Int, Vector[Int]] = this.apply()
  override def apply(): mutable.Builder[Int, Vector[Int]] = Vector.newBuilder
}
// Exiting paste mode, now interpreting.
scala> List(1,2,3).flatMap(List(_))
res6: Vector[Int] = Vector(1, 2, 3)
                        Well... That implicit CanBuildFrom can be used to directly build different type of structure instead of List and thus saving one extra step. lets look at following example,
val list = List(List(1, 2, 3), List(4, 5, 6))
// now if we do a flatmap withtout overriding the implicit CanBuildFrom
val newList = list.flatMap(l => l.map(i => (i,i)))
// new list will be a List[(Int, Int)]
// but what if you wanted a map
val newMap = newList.toMap
// But you actually needed to traverse the list twice in this case
// But we can avoid the second traversal if we chose to override the implicit
val newMap2 = list.flatMap(l => l.map(i => (i,i)))(collection.breakout)
                        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