summaryrefslogtreecommitdiff
path: root/src/library/scala/collection/immutable/Vector.scala
diff options
context:
space:
mode:
authorRex Kerr <ichoran@gmail.com>2015-01-30 18:05:24 -0800
committerRex Kerr <ichoran@gmail.com>2015-06-18 12:04:27 -0700
commitbb4b79c5d1f6bffc2ad6e8466be2dce6a44c0fcb (patch)
tree8553ef89fdf1e479763c134a89efab4561c694c0 /src/library/scala/collection/immutable/Vector.scala
parent23bfa691e2c7372f52958912ff7dbf1cadc1a50c (diff)
downloadscala-bb4b79c5d1f6bffc2ad6e8466be2dce6a44c0fcb.tar.gz
scala-bb4b79c5d1f6bffc2ad6e8466be2dce6a44c0fcb.tar.bz2
scala-bb4b79c5d1f6bffc2ad6e8466be2dce6a44c0fcb.zip
SI-8930 - Vector updated, +:, and :+ slow when typed as Seq[A]
Vector was intercepting only the IndexedSeq CanBuildFrom to quickly generate new vectors. Now it intercepts immutable.Seq and collection.Seq as well. There are other possibilities (collection.IndexedSeq), but they will probably arise rarely, and to avoid an absurdly long set of checks we would need a marker trait (that is not binary compatible).
Diffstat (limited to 'src/library/scala/collection/immutable/Vector.scala')
-rw-r--r--src/library/scala/collection/immutable/Vector.scala17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index 47a623a616..46d5d0c69c 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -132,19 +132,25 @@ override def companion: GenericCompanion[Vector] = Vector
throw new IndexOutOfBoundsException(index.toString)
}
-
+ // If we have a default builder, there are faster ways to perform some operations
+ @inline private[this] def isDefaultCBF[A, B, That](bf: CanBuildFrom[Vector[A], B, That]): Boolean =
+ (bf eq IndexedSeq.ReusableCBF) || (bf eq collection.immutable.Seq.ReusableCBF) || (bf eq collection.Seq.ReusableCBF)
+
// SeqLike api
override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
- if (bf eq IndexedSeq.ReusableCBF) updateAt(index, elem).asInstanceOf[That] // just ignore bf
+ if (isDefaultCBF[A, B, That](bf))
+ updateAt(index, elem).asInstanceOf[That] // ignore bf--it will just give a Vector, and slowly
else super.updated(index, elem)(bf)
override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
- if (bf eq IndexedSeq.ReusableCBF) appendFront(elem).asInstanceOf[That] // just ignore bf
+ if (isDefaultCBF[A, B, That](bf))
+ appendFront(elem).asInstanceOf[That] // ignore bf--it will just give a Vector, and slowly
else super.+:(elem)(bf)
override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
- if (bf eq IndexedSeq.ReusableCBF) appendBack(elem).asInstanceOf[That] // just ignore bf
+ if (isDefaultCBF(bf))
+ appendBack(elem).asInstanceOf[That] // ignore bf--it will just give a Vector, and slowly
else super.:+(elem)(bf)
override def take(n: Int): Vector[A] = {
@@ -211,7 +217,8 @@ override def companion: GenericCompanion[Vector] = Vector
// concat (suboptimal but avoids worst performance gotchas)
override def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Vector[A], B, That]): That = {
- if (bf eq IndexedSeq.ReusableCBF) {
+ if (isDefaultCBF(bf)) {
+ // We are sure we will create a Vector, so let's do it efficiently
import Vector.{Log2ConcatFaster, TinyAppendFaster}
if (that.isEmpty) this.asInstanceOf[That]
else {