Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is VectorBuilder in the package scala.collections.immutable?

VectorBuilder is defined in the same source file as Vector. Vector is immutable and in the scala.collections.immutable package, so as a consequence the builder is in the same package.

As far as I can tell, CanBuildFrom uses a VectorBuilder as the default, if the return type is not explicitly typed.

  • Is there a reason for not having the builder in a separate file in the mutable package?
  • Is the builder not meant to be used directly? If so, which builder or buffer is to be used to create a Seq?
like image 221
Beryllium Avatar asked Jul 11 '13 17:07

Beryllium


1 Answers

VectorBuilder is not meant to be used directly. If you want to get a builder for a Vector, you only need to call Vector.newBuilder[T], which returns a Builder[T, Vector[T]] (with the underlying instance being a VectorBuilder).

So if you want the default builder that would be used to create a Seq, you only need to call Seq.newBuilder:

scala> Seq(1,2,3)
res0: Seq[Int] = List(1, 2, 3)

scala> Seq.newBuilder[Int]
res1: scala.collection.mutable.Builder[Int,Seq[Int]] = ListBuffer()

scala> Seq.newBuilder[Int].result
res2: Seq[Int] = List()

The above shows that the default implementation of Seq is list, and, logically, the default builder for a Seq is actually a mutable.ListBuffer.

ListBuffer is more than just a List builder, that's why it is in collection.mutable whereas VectorBuilder is not a Buffer, it cannot be used for anything else other than build a Vector. That's probably why it is defined locally in Vector. I am not sure why it isn't private, I cannot see it referenced anywhere in the public API of Vector itself. Maybe it should be (private).


Just for reference, there is no hidden magic happening with CanBuildFrom, it almost always just goes through the newBuilder above:

  1. When you do not specify the expected collection type, as in Seq(1,2).map(_+1), the only available CanBuildFrom comes from the companion object a Seq, and is of type CanBuildFrom[Seq[_], T, Seq[T]]. That means the result will be a Seq too.

  2. Like most companion objects of collections, the CanBuildFrom instance Seq provides only does one thing: call Seq.newBuilder (that's defined in GenTraversableFactory ...)

That's why CanBuildFrom for Vector uses a VectorBuilder. For example, in this:

scala> Vector(1,2,3).map(_+1)
res12: scala.collection.immutable.Vector[Int] = Vector(2, 3, 4)

The builder that was used is:

scala> implicitly[CanBuildFrom[Vector[Int], Int, Vector[Int]]].apply()
res13: scala.collection.mutable.Builder[Int,Vector[Int]] = 
  scala.collection.immutable.VectorBuilder@43efdf93
like image 137
gourlaysama Avatar answered Sep 20 '22 15:09

gourlaysama