From 85b699ec11a0998fca5925e24115125bb924874b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 9 Feb 2021 11:18:28 +0100 Subject: [PATCH 01/10] Add missing IArray operations --- library/src/scala/IArray.scala | 798 +++++++++++++++++++++++++++++++-- tests/run/IArrayOps.check | 162 +++++++ tests/run/IArrayOps.scala | 285 ++++++++++++ 3 files changed, 1214 insertions(+), 31 deletions(-) create mode 100644 tests/run/IArrayOps.check create mode 100644 tests/run/IArrayOps.scala diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 20753409a315..9c06741e6863 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -1,7 +1,8 @@ package scala import reflect.ClassTag -import scala.collection.immutable +import scala.collection._ +import scala.collection.mutable.Buffer opaque type IArray[+T] = Array[_ <: T] @@ -39,15 +40,10 @@ object IArray: extension (arr: IArray[Object]) def length: Int = arr.asInstanceOf[Array[Object]].length extension [T](arr: IArray[T]) def length: Int = arr.asInstanceOf[Array[T]].length - /** Returns this array concatenated with the given array. */ - extension [T](arr: IArray[T]) def ++ [U >: T: ClassTag](that: IArray[U]): IArray[U] = - genericArrayOps(arr) ++ that /** Tests whether this array contains a given value as an element. */ extension [T](arr: IArray[T]) def contains(elem: T): Boolean = - // `genericArrayOps(arr).contains(elem)` does not work because `elem` does not have type `arr.T` - // but we can use `exists` instead, which is how `ArrayOps#contains` itself is implemented: - genericArrayOps(arr).exists(_ == elem) + genericArrayOps(arr).contains(elem.asInstanceOf) /** Copy elements of this array to another array. */ extension [T](arr: IArray[T]) def copyToArray[U >: T](xs: Array[U]): Int = @@ -100,7 +96,7 @@ object IArray: /** Flattens a two-dimensional array by concatenating all its rows * into a single array. */ - extension [T](arr: IArray[T]) def flatten[U: ClassTag](using T => Iterable[U]): IArray[U] = + extension [T](arr: IArray[T]) def flatten[U](using asIterable: T => Iterable[U], ct: ClassTag[U]): IArray[U] = genericArrayOps(arr).flatten /** Folds the elements of this array using the specified associative binary operator. */ @@ -135,9 +131,6 @@ object IArray: /** Finds index of first occurrence of some value in this array after or at some start index. */ extension [T](arr: IArray[T]) def indexOf(elem: T, from: Int = 0): Int = - // `asInstanceOf` needed because `elem` does not have type `arr.T` - // We could use `arr.iterator.indexOf(elem, from)` or `arr.indexWhere(_ == elem, from)` - // but these would incur some overhead. genericArrayOps(arr).indexOf(elem.asInstanceOf, from) /** Finds index of the first element satisfying some predicate after or at some start index. */ @@ -170,7 +163,6 @@ object IArray: /** Finds index of last occurrence of some value in this array before or at a given end index. */ extension [T](arr: IArray[T]) def lastIndexOf(elem: T, end: Int = arr.length - 1): Int = - // see: same issue in `indexOf` genericArrayOps(arr).lastIndexOf(elem.asInstanceOf, end) /** Finds index of last element satisfying some predicate before or at given end index. */ @@ -236,10 +228,6 @@ object IArray: extension [T](arr: IArray[T]) def splitAt(n: Int): (IArray[T], IArray[T]) = genericArrayOps(arr).splitAt(n) - /** Tests whether this array starts with the given array. */ - extension [T](arr: IArray[T]) def startsWith[U >: T](that: IArray[U], offset: Int = 0): Boolean = - genericArrayOps(arr).startsWith(that) - /** The rest of the array without its first element. */ extension [T](arr: IArray[T]) def tail: IArray[T] = genericArrayOps(arr).tail @@ -260,15 +248,133 @@ object IArray: extension [T](arr: IArray[T]) def toArray: Array[T] = arr.clone.asInstanceOf[Array[T]] - /** Converts an array of pairs into an array of first elements and an array of second elements. */ - extension [U: ClassTag, V: ClassTag](arr: IArray[(U, V)]) def unzip: (IArray[U], IArray[V]) = - genericArrayOps(arr).unzip - - /** Returns an array formed from this array and another iterable collection - * by combining corresponding elements in pairs. - * If one of the two collections is longer than the other, its remaining elements are ignored. */ - extension [T](arr: IArray[T]) def zip[U](that: IArray[U]): IArray[(T, U)] = - genericArrayOps(arr).zip(that) + extension [T](arr: IArray[T]) + def ++[U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr) ++ suffix.toSeq + def ++[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr) ++ suffix + def :+ [U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr) :+ x + def :++ [U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr) :++ suffix + def :++ [U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr) :++ suffix + def addString(b: mutable.StringBuilder): mutable.StringBuilder = arr.toSeq.addString(b) + def addString(b: mutable.StringBuilder, sep: String): mutable.StringBuilder = arr.toSeq.addString(b, sep) + def addString(b: mutable.StringBuilder, start: String, sep: String, end: String): mutable.StringBuilder = arr.toSeq.addString(b, start, sep, end) + def appended[U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr).appended(x) + def appendedAll[U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr).appendedAll(suffix) + def appendedAll[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr).appendedAll(suffix) + def collect[U: ClassTag](pf: PartialFunction[T, U]): IArray[U] = genericArrayOps(arr).collect(pf) + def collectFirst[U](f: PartialFunction[T, U]): Option[U] = genericArrayOps(arr).collectFirst(f) + def combinations(n: Int): Iterator[IArray[T]] = genericArrayOps(arr).combinations(n) + def concat[U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr).concat(suffix) + def concat[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr).concat(suffix) + def containsSlice[U](that: IArray[U]): Boolean = arr.toSeq.containsSlice(that.toSeq) + def containsSlice[U](that: Seq[U]): Boolean = arr.toSeq.containsSlice(that) + def corresponds[U](that: IArray[U])(p: (T, U) => Boolean): Boolean = arr.toSeq.corresponds(that.toSeq)(p) + def corresponds[U](that: IterableOnce[U])(p: (T, U) => Boolean): Boolean = arr.toSeq.corresponds(that)(p) + def diff[U >: T](that: IArray[U]): IArray[T] = genericArrayOps(arr).diff(that.toSeq) + def diff[U >: T](that: Seq[U]): IArray[T] = genericArrayOps(arr).diff(that) + def distinct: IArray[T] = genericArrayOps(arr).distinct + def distinctBy[U](f: T => U): IArray[T] = genericArrayOps(arr).distinctBy(f) + def empty: immutable.ArraySeq[T] = arr.toSeq.empty + def startsWith[U >: T](that: IArray[U]): Boolean = genericArrayOps(arr).startsWith(that, 0) + def startsWith[U >: T](that: IArray[U], offset: Int): Boolean = genericArrayOps(arr).startsWith(that, offset) + def startsWith[U >: T](that: IterableOnce[U]): Boolean = genericArrayOps(arr).startsWith(that, 0) + def startsWith[U >: T](that: IterableOnce[U], offset: Int): Boolean = genericArrayOps(arr).startsWith(that, offset) + def endsWith[U >: T](that: IArray[U]): Boolean = genericArrayOps(arr).endsWith(that) + def endsWith[U >: T](that: Iterable[U]): Boolean = genericArrayOps(arr).endsWith(that) + def findLast(p: T => Boolean): Option[T] = arr.toSeq.findLast(p) + def groupBy[K](f: T => K): immutable.Map[K, IArray[T]] = genericArrayOps(arr).groupBy(f) + def groupMap[K, U: ClassTag](key: T => K)(f: T => U): immutable.Map[K, IArray[U]] = genericArrayOps(arr).groupMap(key)(f) + def groupMapReduce[K, U](key: (T) => K)(f: (T) => U)(reduce: (U, U) => U): immutable.Map[K, U] = arr.toSeq.groupMapReduce(key)(f)(reduce) + def grouped(size: Int): Iterator[IArray[T]] = genericArrayOps(arr).grouped(size) + def indexOfSlice[U >: T](that: IArray[U]): Int = arr.toSeq.indexOfSlice(that) + def indexOfSlice[U >: T](that: Seq[U]): Int = arr.toSeq.indexOfSlice(that) + def indexOfSlice[U >: T](that: IArray[U], from: Int): Int = arr.toSeq.indexOfSlice(that, from) + def indexOfSlice[U >: T](that: Seq[U], from: Int): Int = arr.toSeq.indexOfSlice(that, from) + def inits: Iterator[IArray[T]] = genericArrayOps(arr).inits + def intersect[U >: T](that: IArray[U]): IArray[T] = genericArrayOps(arr).intersect(that) + def intersect[U >: T](that: Seq[U]): IArray[T] = genericArrayOps(arr).intersect(that) + def isTraversableAgain: Boolean = arr.toSeq.isTraversableAgain + def knownSize: Int = arr.length + def lastIndexOfSlice[U >: T](that: IArray[U]): Int = arr.toSeq.lastIndexOfSlice(that) + def lastIndexOfSlice[U >: T](that: Seq[U]): Int = arr.toSeq.lastIndexOfSlice(that) + def lastIndexOfSlice[U >: T](that: IArray[U], end: Int): Int = arr.toSeq.lastIndexOfSlice(that, end) + def lastIndexOfSlice[U >: T](that: Seq[U], end: Int): Int = arr.toSeq.lastIndexOfSlice(that, end) + def lazyZip[U](that: IArray[U]): LazyZip2[T, U, IArray[T]] = genericArrayOps(arr).lazyZip[U](that).asInstanceOf[LazyZip2[T, U, IArray[T]]] + def lazyZip[U](that: Iterable[U]): LazyZip2[T, U, IArray[T]] = genericArrayOps(arr).lazyZip[U](that).asInstanceOf[LazyZip2[T, U, IArray[T]]] + def lengthCompare(len: Int): Int = genericArrayOps(arr).lengthCompare(len) + def lengthIs: IterableOps.SizeCompareOps = arr.toSeq.lengthIs + def max[U >: T](using math.Ordering[U]): T = arr.toSeq.max[U] + def maxBy[U](f: T => U)(using math.Ordering[U]): T = arr.toSeq.maxBy(f) + def maxByOption[U](f: T => U)(using math.Ordering[U]): Option[T] = arr.toSeq.maxByOption(f) + def maxOption[U >: T](using math.Ordering[U]): Option[U] = arr.toSeq.maxOption[U] + def min[U >: T](using math.Ordering[U]): T = arr.toSeq.min[U] + def minBy[U](f: T => U)(using math.Ordering[U]): T = arr.toSeq.minBy(f) + def minByOption[U](f: T => U)(using math.Ordering[U]): Option[T] = arr.toSeq.minByOption(f) + def minOption[U >: T](using math.Ordering[U]): Option[U] = arr.toSeq.minOption[U] + def mkString: String = arr.toSeq.mkString + def mkString(sep: String): String = arr.toSeq.mkString(sep) + def mkString(start: String, sep: String, end: String): String = arr.toSeq.mkString(start, sep, end) + def padTo[U >: T: ClassTag](len: Int, elem: U): IArray[U] = genericArrayOps(arr).padTo(len, elem) + def partitionMap[T1: ClassTag, T2: ClassTag](f: T => Either[T1, T2]): (IArray[T1], IArray[T2]) = genericArrayOps(arr).partitionMap(f) + def patch[U >: T: ClassTag](from: Int, other: IterableOnce[U], replaced: Int): IArray[U] = genericArrayOps(arr).patch(from, other, replaced) + def permutations: Iterator[IArray[T]] = genericArrayOps(arr).permutations + def prepended[U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr).prepended(x) + def prependedAll[U >: T: ClassTag](prefix: IterableOnce[U]): IArray[U] = genericArrayOps(arr).prependedAll(prefix) + def product[U >: T](using math.Numeric[U]): U = arr.toSeq.product[U] + def reduce[U >: T](op: (U, U) => U): U = arr.toSeq.reduce(op) + def reduceLeft[U >: T](op: (U, T) => U): U = arr.toSeq.reduceLeft(op) + def reduceRight[U >: T](op: (T, U) => U): U = arr.toSeq.reduceRight(op) + def reverseIterator: Iterator[T] = genericArrayOps(arr).reverseIterator + def sameElements[U >: T](that: IArray[U]): Boolean = arr.toSeq.sameElements(that) + def sameElements[U >: T](that: IterableOnce[U]): Boolean = arr.toSeq.sameElements(that) + def search[U >: T](elem: U)(using Ordering[U]): Searching.SearchResult = arr.toSeq.search(elem) + def search[U >: T](elem: U, from: Int, to: Int)(using Ordering[U]): Searching.SearchResult = arr.toSeq.search(elem, from, to) + def segmentLength(p: (T) => Boolean, from: Int): Int = arr.toSeq.segmentLength(p, from) + def segmentLength(p: (T) => Boolean): Int = arr.toSeq.segmentLength(p) + def sizeCompare(that: IArray[Any]): Int = arr.toSeq.sizeCompare(that) + def sizeCompare(that: Iterable[_]): Int = arr.toSeq.sizeCompare(that) + def sizeCompare(otherSize: Int): Int = genericArrayOps(arr).sizeCompare(otherSize) + def sizeIs: IterableOps.SizeCompareOps = arr.toSeq.sizeIs + def sliding(size: Int, step: Int = 1): Iterator[IArray[T]] = genericArrayOps(arr).sliding(size, step) + def stepper[S <: Stepper[_]](using StepperShape[T, S]): S = genericArrayOps(arr).stepper[S] + def sum[U >: T](using math.Numeric[U]): U = arr.toSeq.sum[U] + def tails: Iterator[IArray[T]] = genericArrayOps(arr).tails + def tapEach[U](f: (T) => U): IArray[T] = + arr.toSeq.foreach(f) + arr + def to[C1](factory: Factory[T, C1]): C1 = arr.toSeq.to(factory) + def toBuffer[U >: T]: Buffer[U] = arr.toSeq.toBuffer[U] + def toIndexedSeq: immutable.IndexedSeq[T] = arr.toSeq.toIndexedSeq + def toIterable: Iterable[T] = arr.toSeq.toIterable + def toList: List[T] = arr.toSeq.toList + def toSet: Set[T] = arr.toSeq.toSet + def toVector: Vector[T] = arr.toSeq.toVector + def unzip[T1, T2](using asPair: T => (T1, T2), ct1: ClassTag[T1], ct2: ClassTag[T2]): (IArray[T1], IArray[T2]) = genericArrayOps(arr).unzip + def unzip3[T1, T2, T3](using asTriple: T => (T1, T2, T3), ct1: ClassTag[T1], ct2: ClassTag[T2], ct3: ClassTag[T3]): (IArray[T1], IArray[T2], IArray[T3]) = genericArrayOps(arr).unzip3 + def updated[U >: T: ClassTag](index: Int, elem: U): IArray[U] = genericArrayOps(arr).updated(index, elem) + def view: SeqView[T] = genericArrayOps(arr).view + def withFilter(p: T => Boolean): WithFilter[T] = new WithFilter(p, arr) + def zip[U](that: IArray[U]): IArray[(T, U)] = genericArrayOps(arr).zip(that) + def zip[U](that: IterableOnce[U]): IArray[(T, U)] = genericArrayOps(arr).zip(that) + def zipAll[T1 >: T, U](that: IArray[U], thisElem: T1, thatElem: U): IArray[(T1, U)] = genericArrayOps(arr).zipAll(that, thisElem, thatElem) + def zipAll[T1 >: T, U](that: Iterable[U], thisElem: T1, thatElem: U): IArray[(T1, U)] = genericArrayOps(arr).zipAll(that, thisElem, thatElem) + def zipWithIndex: IArray[(T, Int)] = genericArrayOps(arr).zipWithIndex + end extension + + extension [T](arr: IArray[T]) + def transpose[U](implicit asArray: T => IArray[U]): IArray[IArray[U]] = + genericArrayOps(arr).transpose(using asArray.asInstanceOf[T => Array[U]]) + + extension [T, U >: T: ClassTag](prefix: IterableOnce[T]) + def ++:(arr: IArray[U]): IArray[U] = genericArrayOps(arr).prependedAll(prefix) + + extension [T, U >: T: ClassTag](prefix: IArray[T]) + def ++:(arr: IArray[U]): IArray[U] = genericArrayOps(arr).prependedAll(prefix) + + extension [T, U >: T: ClassTag](x: T) + def +:(arr: IArray[U]): IArray[U] = genericArrayOps(arr).prepended(x) + + extension [T1, T2](arr: IArray[(T1, T2)]) + def toMap: Map[T1, T2] = arr.toSeq.toMap /** Conversion from IArray to immutable.ArraySeq */ extension [T](arr: IArray[T]) def toSeq: immutable.ArraySeq[T] = @@ -314,6 +420,39 @@ object IArray: extension (arr: IArray[Unit]) def toSeq: immutable.ArraySeq[Unit] = immutable.ArraySeq.ofUnit(arr.asInstanceOf[Array[Unit]]) + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapIArray[T](using DummyImplicit): Conversion[IArray[T], immutable.ArraySeq[T]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapAnyRefIArray[T <: AnyRef](using DummyImplicit): Conversion[IArray[T], immutable.ArraySeq[T]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapIntIArray(using DummyImplicit): Conversion[IArray[Int], immutable.ArraySeq[Int]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapDoubleIArray(using DummyImplicit): Conversion[IArray[Double], immutable.ArraySeq[Double]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapLongIArray(using DummyImplicit): Conversion[IArray[Long], immutable.ArraySeq[Long]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapFloatIArray(using DummyImplicit): Conversion[IArray[Float], immutable.ArraySeq[Float]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapCharIArray(using DummyImplicit): Conversion[IArray[Char], immutable.ArraySeq[Char]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapByteIArray(using DummyImplicit): Conversion[IArray[Byte], immutable.ArraySeq[Byte]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapShortIArray(using DummyImplicit): Conversion[IArray[Short], immutable.ArraySeq[Short]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapBooleanIArray(using DummyImplicit): Conversion[IArray[Boolean], immutable.ArraySeq[Boolean]] = _.toSeq + + /** Conversion from IArray to immutable.ArraySeq */ + given genericWrapUnitIArray(using DummyImplicit): Conversion[IArray[Unit], immutable.ArraySeq[Unit]] = _.toSeq + /** Convert an array into an immutable array without copying, the original array * must _not_ be mutated after this or the guaranteed immutablity of IArray will * be violated. @@ -363,16 +502,32 @@ object IArray: /** An immutable array with given elements. */ def apply(x: Unit, xs: Unit*): IArray[Unit] = Array(x, xs: _*) + /** Build an array from the iterable collection. + * + * {{{ + * scala> val a = Array.from(Seq(1, 5)) + * val a: Array[Int] = Array(1, 5) + * + * scala> val b = Array.from(Range(1, 5)) + * val b: Array[Int] = Array(1, 2, 3, 4) + * }}} + * + * @param it the iterable collection + * @return an array consisting of elements of the iterable collection + */ + def from[A : ClassTag](it: IterableOnce[A]): Array[A] = + Array.from(it) + + def newBuilder[T](using t: ClassTag[T]): IArrayBuilder[T] = + IArrayBuilder.make[T] + /** Concatenates all arrays into a single immutable array. * * @param xss the given immutable arrays * @return the array created from concatenating `xss` */ def concat[T: ClassTag](xss: IArray[T]*): IArray[T] = - // `Array.concat` should arguably take in a `Seq[Array[_ <: T]]`, - // but since it currently takes a `Seq[Array[T]]` we have to perform a cast, - // knowing tacitly that `concat` is not going to do the wrong thing. - Array.concat[T](xss.asInstanceOf[Seq[Array[T]]]: _*) + Array.concat[T](xss.asInstanceOf[immutable.Seq[Array[T]]]: _*) /** Returns an immutable array that contains the results of some element computation a number * of times. Each element is determined by a separate computation. @@ -391,7 +546,6 @@ object IArray: * @param elem the element computation */ def fill[T: ClassTag](n1: Int, n2: Int)(elem: => T): IArray[IArray[T]] = - // We cannot avoid a cast here as Array.fill creates inner arrays out of our control: Array.fill(n1, n2)(elem) /** Returns a three-dimensional immutable array that contains the results of some element computation a number @@ -512,6 +666,17 @@ object IArray: */ def iterate[T: ClassTag](start: T, len: Int)(f: T => T): IArray[T] = Array.iterate(start, len)(f) + /** Compare two arrays per element. + * + * A more efficient version of `xs.sameElements(ys)`. + * + * @param xs an array of AnyRef + * @param ys an array of AnyRef + * @return true if corresponding elements are equal + */ + def equals(xs: IArray[AnyRef], ys: IArray[AnyRef]): Boolean = + Array.equals(xs.asInstanceOf[Array[AnyRef]], ys.asInstanceOf[Array[AnyRef]]) + /** Returns a decomposition of the array into a sequence. This supports * a pattern match like `{ case IArray(x,y,z) => println('3 elements')}`. * @@ -521,4 +686,575 @@ object IArray: def unapplySeq[T](x: IArray[T]): Array.UnapplySeqWrapper[_ <: T] = Array.unapplySeq(x) -end IArray \ No newline at end of file + /** A lazy filtered array. No filtering is applied until one of `foreach`, `map` or `flatMap` is called. */ + class WithFilter[T](p: T => Boolean, xs: IArray[T]): + + /** Apply `f` to each element for its side effects. + * Note: [U] parameter needed to help scalac's type inference. + */ + def foreach[U](f: T => U): Unit = { + val len = xs.length + var i = 0 + while(i < len) { + val x = xs(i) + if(p(x)) f(x) + i += 1 + } + } + + /** Builds a new array by applying a function to all elements of this array. + * + * @param f the function to apply to each element. + * @tparam U the element type of the returned array. + * @return a new array resulting from applying the given function + * `f` to each element of this array and collecting the results. + */ + def map[U: ClassTag](f: T => U): IArray[U] = { + val b = IArrayBuilder.make[U] + var i = 0 + while (i < xs.length) { + val x = xs(i) + if(p(x)) b += f(x) + i = i + 1 + } + b.result() + } + + /** Builds a new array by applying a function to all elements of this array + * and using the elements of the resulting collections. + * + * @param f the function to apply to each element. + * @tparam U the element type of the returned array. + * @return a new array resulting from applying the given collection-valued function + * `f` to each element of this array and concatenating the results. + */ + def flatMap[U: ClassTag](f: T => IterableOnce[U]): IArray[U] = { + val b = IArrayBuilder.make[U] + var i = 0 + while(i < xs.length) { + val x = xs(i) + if(p(x)) b ++= f(xs(i)) + i += 1 + } + b.result() + } + + def flatMap[BS, U](f: T => BS)(using asIterable: BS => Iterable[U], m: ClassTag[U]): IArray[U] = + flatMap[U](x => asIterable(f(x))) + + /** Creates a new non-strict filter which combines this filter with the given predicate. */ + def withFilter(q: T => Boolean): WithFilter[T] = new WithFilter[T](a => p(a) && q(a), xs) + + end WithFilter + + /** A builder class for immutable arrays. + * + * @tparam T the type of the elements for the builder. + */ + @SerialVersionUID(3L) + sealed abstract class IArrayBuilder[T] + extends mutable.ReusableBuilder[T, IArray[T]] + with Serializable { + protected[this] var capacity: Int = 0 + protected[this] def elems: Array[T] + protected var size: Int = 0 + + def length: Int = size + + override def knownSize: Int = size + + protected[this] final def ensureSize(size: Int): Unit = { + if (capacity < size || capacity == 0) { + var newsize = if (capacity == 0) 16 else capacity * 2 + while (newsize < size) newsize *= 2 + resize(newsize) + } + } + + override final def sizeHint(size: Int): Unit = + if (capacity < size) resize(size) + + def clear(): Unit = size = 0 + + protected[this] def resize(size: Int): Unit + + /** Add all elements of an array */ + def addAll(xs: IArray[T]): this.type = addAll(xs, 0, xs.length) + + /** Add a slice of an array */ + def addAll(xs: IArray[T], offset: Int, length: Int): this.type = { + ensureSize(this.size + length) + Array.copy(xs.asInstanceOf[Array[T]], offset, elems, this.size, length) + size += length + this + } + + override def addAll(xs: IterableOnce[T]): this.type = { + val k = xs.knownSize + if (k > 0) { + ensureSize(this.size + k) + // IterableOnce.copyElemsToArray(xs, elems, this.size) + // manually inlined as + xs match { + case src: Iterable[T] => src.copyToArray[T](elems, this.size, Int.MaxValue) + case src => src.iterator.copyToArray[T](elems, this.size, Int.MaxValue) + } + size += k + } else if (k < 0) super.addAll(xs) + this + } + } + + /** A companion object for array builders. + */ + object IArrayBuilder { + + /** Creates a new arraybuilder of type `T`. + * + * @tparam T type of the elements for the array builder, with a `ClassTag` context bound. + * @return a new empty array builder. + */ + @inline def make[T: ClassTag]: IArrayBuilder[T] = { + val tag = implicitly[ClassTag[T]] + tag.runtimeClass match { + case java.lang.Byte.TYPE => new IArrayBuilder.ofByte().asInstanceOf[IArrayBuilder[T]] + case java.lang.Short.TYPE => new IArrayBuilder.ofShort().asInstanceOf[IArrayBuilder[T]] + case java.lang.Character.TYPE => new IArrayBuilder.ofChar().asInstanceOf[IArrayBuilder[T]] + case java.lang.Integer.TYPE => new IArrayBuilder.ofInt().asInstanceOf[IArrayBuilder[T]] + case java.lang.Long.TYPE => new IArrayBuilder.ofLong().asInstanceOf[IArrayBuilder[T]] + case java.lang.Float.TYPE => new IArrayBuilder.ofFloat().asInstanceOf[IArrayBuilder[T]] + case java.lang.Double.TYPE => new IArrayBuilder.ofDouble().asInstanceOf[IArrayBuilder[T]] + case java.lang.Boolean.TYPE => new IArrayBuilder.ofBoolean().asInstanceOf[IArrayBuilder[T]] + case java.lang.Void.TYPE => new IArrayBuilder.ofUnit().asInstanceOf[IArrayBuilder[T]] + case _ => new IArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[IArrayBuilder[T]] + } + } + + /** A class for array builders for arrays of reference types. + * + * This builder can be reused. + * + * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassTag` context bound. + */ + @SerialVersionUID(3L) + final class ofRef[T <: AnyRef](implicit ct: ClassTag[T]) extends IArrayBuilder[T] { + + protected var elems: Array[T] = _ + + private def mkArray(size: Int): Array[T] = { + if (capacity == this.size && capacity > 0) elems + else if (elems eq null) new Array[T](size) + else java.util.Arrays.copyOf[T](elems, size) + } + + protected[this] def resize(size: Int): Unit = { + elems = mkArray(size) + capacity = size + } + + def addOne(elem: T): this.type = { + ensureSize(this.size + 1) + elems(this.size) = elem + this.size += 1 + this + } + + def result(): IArray[T] = { + if (capacity != 0 && capacity == this.size) { + capacity = 0 + val res = elems + elems = null + IArray.unsafeFromArray(res) + } + else IArray.unsafeFromArray(mkArray(this.size)) + } + + override def clear(): Unit = { + super.clear() + if(elems ne null) java.util.Arrays.fill(elems.asInstanceOf[Array[AnyRef]], null) + } + + override def equals(other: Any): Boolean = other match { + case x: ofRef[_] => (this.size == x.size) && (elems == x.elems) + case _ => false + } + + override def toString = "IArrayBuilder.ofRef" + } + + /** A class for array builders for arrays of `byte`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofByte extends IArrayBuilder[Byte] { + + protected var elems: Array[Byte] = _ + + private def mkArray(size: Int): Array[Byte] = { + val newelems = new Array[Byte](size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + newelems + } + + protected[this] def resize(size: Int): Unit = { + elems = mkArray(size) + capacity = size + } + + def addOne(elem: Byte): this.type = { + ensureSize(this.size + 1) + elems(this.size) = elem + this.size += 1 + this + } + + def result(): IArray[Byte] = { + if (capacity != 0 && capacity == this.size) { + capacity = 0 + val res = elems + elems = null + IArray.unsafeFromArray(res) + } + else IArray.unsafeFromArray(mkArray(this.size)) + } + + override def equals(other: Any): Boolean = other match { + case x: ofByte => (this.size == x.size) && (elems == x.elems) + case _ => false + } + + override def toString = "IArrayBuilder.ofByte" + } + + /** A class for array builders for arrays of `short`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofShort extends IArrayBuilder[Short] { + + protected var elems: Array[Short] = _ + + private def mkArray(size: Int): Array[Short] = { + val newelems = new Array[Short](size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + newelems + } + + protected[this] def resize(size: Int): Unit = { + elems = mkArray(size) + capacity = size + } + + def addOne(elem: Short): this.type = { + ensureSize(this.size + 1) + elems(this.size) = elem + this.size += 1 + this + } + + def result(): IArray[Short] = { + if (capacity != 0 && capacity == this.size) { + capacity = 0 + val res = elems + elems = null + IArray.unsafeFromArray(res) + } + else IArray.unsafeFromArray(mkArray(this.size)) + } + + override def equals(other: Any): Boolean = other match { + case x: ofShort => (this.size == x.size) && (elems == x.elems) + case _ => false + } + + override def toString = "IArrayBuilder.ofShort" + } + + /** A class for array builders for arrays of `char`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofChar extends IArrayBuilder[Char] { + + protected var elems: Array[Char] = _ + + private def mkArray(size: Int): Array[Char] = { + val newelems = new Array[Char](size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + newelems + } + + protected[this] def resize(size: Int): Unit = { + elems = mkArray(size) + capacity = size + } + + def addOne(elem: Char): this.type = { + ensureSize(this.size + 1) + elems(this.size) = elem + this.size += 1 + this + } + + def result(): IArray[Char] = { + if (capacity != 0 && capacity == this.size) { + capacity = 0 + val res = elems + elems = null + IArray.unsafeFromArray(res) + } + else IArray.unsafeFromArray(mkArray(this.size)) + } + + override def equals(other: Any): Boolean = other match { + case x: ofChar => (this.size == x.size) && (elems == x.elems) + case _ => false + } + + override def toString = "IArrayBuilder.ofChar" + } + + /** A class for array builders for arrays of `int`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofInt extends IArrayBuilder[Int] { + + protected var elems: Array[Int] = _ + + private def mkArray(size: Int): Array[Int] = { + val newelems = new Array[Int](size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + newelems + } + + protected[this] def resize(size: Int): Unit = { + elems = mkArray(size) + capacity = size + } + + def addOne(elem: Int): this.type = { + ensureSize(this.size + 1) + elems(this.size) = elem + this.size += 1 + this + } + + def result(): IArray[Int] = { + if (capacity != 0 && capacity == this.size) { + capacity = 0 + val res = elems + elems = null + IArray.unsafeFromArray(res) + } + else IArray.unsafeFromArray(mkArray(this.size)) + } + + override def equals(other: Any): Boolean = other match { + case x: ofInt => (this.size == x.size) && (elems == x.elems) + case _ => false + } + + override def toString = "IArrayBuilder.ofInt" + } + + /** A class for array builders for arrays of `long`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofLong extends IArrayBuilder[Long] { + + protected var elems: Array[Long] = _ + + private def mkArray(size: Int): Array[Long] = { + val newelems = new Array[Long](size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + newelems + } + + protected[this] def resize(size: Int): Unit = { + elems = mkArray(size) + capacity = size + } + + def addOne(elem: Long): this.type = { + ensureSize(this.size + 1) + elems(this.size) = elem + this.size += 1 + this + } + + def result(): IArray[Long] = { + if (capacity != 0 && capacity == this.size) { + capacity = 0 + val res = elems + elems = null + IArray.unsafeFromArray(res) + } + else IArray.unsafeFromArray(mkArray(this.size)) + } + + override def equals(other: Any): Boolean = other match { + case x: ofLong => (this.size == x.size) && (elems == x.elems) + case _ => false + } + + override def toString = "IArrayBuilder.ofLong" + } + + /** A class for array builders for arrays of `float`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofFloat extends IArrayBuilder[Float] { + + protected var elems: Array[Float] = _ + + private def mkArray(size: Int): Array[Float] = { + val newelems = new Array[Float](size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + newelems + } + + protected[this] def resize(size: Int): Unit = { + elems = mkArray(size) + capacity = size + } + + def addOne(elem: Float): this.type = { + ensureSize(this.size + 1) + elems(this.size) = elem + this.size += 1 + this + } + + def result(): IArray[Float] = { + if (capacity != 0 && capacity == this.size) { + capacity = 0 + val res = elems + elems = null + IArray.unsafeFromArray(res) + } + else IArray.unsafeFromArray(mkArray(this.size)) + } + + override def equals(other: Any): Boolean = other match { + case x: ofFloat => (this.size == x.size) && (elems == x.elems) + case _ => false + } + + override def toString = "IArrayBuilder.ofFloat" + } + + /** A class for array builders for arrays of `double`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofDouble extends IArrayBuilder[Double] { + + protected var elems: Array[Double] = _ + + private def mkArray(size: Int): Array[Double] = { + val newelems = new Array[Double](size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + newelems + } + + protected[this] def resize(size: Int): Unit = { + elems = mkArray(size) + capacity = size + } + + def addOne(elem: Double): this.type = { + ensureSize(this.size + 1) + elems(this.size) = elem + this.size += 1 + this + } + + def result(): IArray[Double] = { + if (capacity != 0 && capacity == this.size) { + capacity = 0 + val res = elems + elems = null + IArray.unsafeFromArray(res) + } + else IArray.unsafeFromArray(mkArray(this.size)) + } + + override def equals(other: Any): Boolean = other match { + case x: ofDouble => (this.size == x.size) && (elems == x.elems) + case _ => false + } + + override def toString = "IArrayBuilder.ofDouble" + } + + /** A class for array builders for arrays of `boolean`s. It can be reused. */ + @SerialVersionUID(3L) + class ofBoolean extends IArrayBuilder[Boolean] { + + protected var elems: Array[Boolean] = _ + + private def mkArray(size: Int): Array[Boolean] = { + val newelems = new Array[Boolean](size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + newelems + } + + protected[this] def resize(size: Int): Unit = { + elems = mkArray(size) + capacity = size + } + + def addOne(elem: Boolean): this.type = { + ensureSize(this.size + 1) + elems(this.size) = elem + this.size += 1 + this + } + + def result(): IArray[Boolean] = { + if (capacity != 0 && capacity == this.size) { + capacity = 0 + val res = elems + elems = null + IArray.unsafeFromArray(res) + } + else IArray.unsafeFromArray(mkArray(this.size)) + } + + override def equals(other: Any): Boolean = other match { + case x: ofBoolean => (this.size == x.size) && (elems == x.elems) + case _ => false + } + + override def toString = "IArrayBuilder.ofBoolean" + } + + /** A class for array builders for arrays of `Unit` type. It can be reused. */ + @SerialVersionUID(3L) + final class ofUnit extends IArrayBuilder[Unit] { + + protected def elems: Array[Unit] = throw new UnsupportedOperationException() + + def addOne(elem: Unit): this.type = { + this.size += 1 + this + } + + override def addAll(xs: IterableOnce[Unit]): this.type = { + this.size += xs.iterator.size + this + } + + override def addAll(xs: IArray[Unit], offset: Int, length: Int): this.type = { + this.size += length + this + } + + def result(): IArray[Unit] = { + val ans = new Array[Unit](this.size) + var i = 0 + while (i < this.size) { ans(i) = (); i += 1 } + IArray.unsafeFromArray(ans) + } + + override def equals(other: Any): Boolean = other match { + case x: ofUnit => (this.size == x.size) + case _ => false + } + + protected[this] def resize(size: Int): Unit = () + + override def toString = "IArrayBuilder.ofUnit" + } + } + +end IArray diff --git a/tests/run/IArrayOps.check b/tests/run/IArrayOps.check new file mode 100644 index 000000000000..847906991768 --- /dev/null +++ b/tests/run/IArrayOps.check @@ -0,0 +1,162 @@ +ArraySeq(1, 2, 3) +true +false +ArraySeq(1, 9, 3) +ArraySeq(1, a, 3) +ArraySeq(1, 2, 3, 0) +ArraySeq(1, 1, 2, 3) +ArraySeq(1, 5, 4, 3) +1 +1 +ArraySeq(1, 5, 4, 3) +ArraySeq(5, 4, 3) +ArraySeq() +ArraySeq(1, 2, 3, 5, 4, 5, 6) +ArraySeq(1, 2, 3, 5, 4, 5, 6) +ArraySeq(1, 2, 3, 7) +ArraySeq(8, 1, 2, 3) +ArraySeq(1, 2, 3, 5, 4, 5, 6) +ArraySeq(5, 4, 5, 6, 12, 13, 14) +ArraySeq(12, 13, 14, 5, 4, 5, 6) +123 +1-2-3 +(1,2,3) +ArraySeq(1, 2, 3, 5) +ArraySeq(1, 2, 3, 5, 4, 5, 6) +ArraySeq(1, 2, 3, 1, 4) +ArraySeq(5, 1, 2, 3) +ArraySeq(5, 6, 1, 2, 3) +ArraySeq(2, 6) +Some(2) +List(ArraySeq(1), ArraySeq(2), ArraySeq(3)) +List(ArraySeq(1, 2), ArraySeq(1, 3), ArraySeq(2, 3)) +List(ArraySeq(1, 2, 3)) +ArraySeq(1, 2, 3, 5, 4, 5, 6) +ArraySeq(1, 2, 3, 8, 9) +false +true +false +true +false +ArraySeq(3) +ArraySeq(3) +ArraySeq(1, 2, 3) +ArraySeq(5, 4, 6) +ArraySeq(5, 4) +false +false +true +true +Some(1) +Some(2) +6 +6 +6 +6 +6 +6 +Map(1 -> ArraySeq(1), 2 -> ArraySeq(2), 3 -> ArraySeq(3)) +Map(0 -> ArraySeq(2), 1 -> ArraySeq(1, 3)) +Map(1 -> ArraySeq(1), 2 -> ArraySeq(2), 3 -> ArraySeq(3)) +Map(0 -> ArraySeq(2), 1 -> ArraySeq(1, 3)) +Map(1 -> 1, 2 -> 2, 3 -> 3) +Map(0 -> 2, 1 -> 13) +List(ArraySeq(1, 2), ArraySeq(3)) +0 +1 +-1 +1 +0 +1 +0 +1 +List(ArraySeq(1, 2, 3), ArraySeq(1, 2), ArraySeq(1), ArraySeq()) +List(ArraySeq(1, 2, 3), ArraySeq(2, 3), ArraySeq(3), ArraySeq()) +ArraySeq(1, 2) +ArraySeq(2, 3) +true +3 +ArraySeq(1, 2, 3).lazyZip(ArraySeq(5, 4, 5, 6)) +List((1,5), (2,4), (3,5)) +0 +1 +-1 +3 +Some(3) +3 +Some(3) +1 +Some(1) +1 +Some(1) +123 +1-2-3 +(1,2,3) +ArraySeq((1,5), (2,4), (3,5)) +ArraySeq((1,5), (2,5), (3,5)) +ArraySeq((1,5), (2,5), (3,4)) +ArraySeq((1,5), (2,5), (3,4)) +ArraySeq(1, 2) +ArraySeq(a, b) +ArraySeq(1, 2) +ArraySeq(a, b) +ArraySeq(x, y) +ArraySeq(1, 2, 3, 0, 0, 0) +ArraySeq(1, 2, 3) +ArraySeq() +ArraySeq() +ArraySeq(1, 2, 3) +ArraySeq(1, 6, 7, 8, 9) +List(ArraySeq(1, 2, 3), ArraySeq(1, 3, 2), ArraySeq(2, 1, 3), ArraySeq(2, 3, 1), ArraySeq(3, 1, 2), ArraySeq(3, 2, 1)) +6 +6 +List(1, 2, 3) +List(3, 2, 1) +true +false +1 +0 +-1 +-1 +1 +List(ArraySeq(1, 2), ArraySeq(2, 3)) +List(ArraySeq(5, 4, 5), ArraySeq(5, 6)) +ArraySeq(6, 5, 5, 4) +true +true +1 +2 +3 +ArraySeq(1, 2, 3) +ArraySeq((1,0), (2,1), (3,2)) +List(1, 2, 3) +Vector(1, 2, 3) +ArrayBuffer(1, 2, 3) +ArraySeq(1, 2, 3) +ArraySeq(1, 2, 3) +List(1, 2, 3) +Set(1, 2, 3) +Vector(1, 2, 3) +ArrayView(1, 2, 3) +Map(1 -> 5, 2 -> 4, 3 -> 5) +Map(1 -> 5, 2 -> 4, 3 -> 5) +ArraySeq() +true +false +false +ArraySeq(1, 2, 2, 3) +Found(1) +ArraySeq(1, 3) +(2,4) +(2,6) +(3,4) +(3,6) +ArraySeq((2,4), (2,6), (3,4), (3,6)) +ArraySeq() +ArraySeq(ArraySeq(1, 4), ArraySeq(2, 5), ArraySeq(3, 6)) +false +ArraySeq(a, b) +ArraySeq(1, 2, 4, 1, 2, 3, 9, 10) +List((1,5), (1,4), (1,5), (1,6), (1,5), (1,4), (1,5), (1,6), (1,5), (1,4), (1,5), (1,6)) +List((1,true,1,2,3,4,5.0,6.0,a,abc,xyz,())) +ArraySeq((1,true,1,2,3,4,5.0,6.0,a,abc,xyz,())) diff --git a/tests/run/IArrayOps.scala b/tests/run/IArrayOps.scala new file mode 100644 index 000000000000..9a2f4672daae --- /dev/null +++ b/tests/run/IArrayOps.scala @@ -0,0 +1,285 @@ +@main def Test: Unit = + val iarr1 = IArray(1, 2, 3) + val iarr2 = IArray(5, 4, 5, 6) + // val iarr3 = IArray( + // IArray(1, 2, 3), + // IArray(4, 5, 6), + // IArray(7, 8, 9) + // ) + + println(iarr1.toSeq) + println(iarr1.contains(1)) + println(iarr1.contains(4)) + println(iarr1.updated(1, 9).toSeq) + println(iarr1.updated(1, "a").toSeq) + + val arr = Array(0, 0, 0, 0) + iarr1.copyToArray(arr) + println(arr.toSeq) + iarr1.copyToArray(arr, 1) + println(arr.toSeq) + iarr2.copyToArray(arr, 1, 2) + println(arr.toSeq) + + println(arr.count(_ == 1)) + println(arr.count(_ <= 2)) + + println(arr.drop(0).toSeq) + println(arr.drop(1).toSeq) + println(arr.drop(6).toSeq) + + println((iarr1 ++ iarr2).toSeq) + println((iarr1 ++ iarr2.toSeq).toSeq) + println((iarr1 :+ 7).toSeq) + println((8 +: iarr1).toSeq) + println((iarr1 :++ iarr2).toSeq) + println((iarr2 :++ List(12, 13, 14)).toSeq) + println((List(12, 13, 14) ++: iarr2).toSeq) + + val sb = StringBuilder() + iarr1.addString(sb).append("\n") + iarr1.addString(sb, "-").append("\n") + iarr1.addString(sb, "(", ",", ")") + println(sb) + + println(iarr1.appended(5).toSeq) + println(iarr1.appendedAll(iarr2).toSeq) + println(iarr1.appendedAll(List(1, 4)).toSeq) + println(iarr1.prepended(5).toSeq) + println(iarr1.prependedAll(List(5, 6)).toSeq) + + println(iarr1.collect { case x if x % 2 == 1 => 2 * x }.toSeq) + println(iarr1.collectFirst { case x if x % 2 == 1 => 2 * x }) + + println(iarr1.combinations(1).map(_.toSeq).toSeq) + println(iarr1.combinations(2).map(_.toSeq).toSeq) + println(iarr1.combinations(3).map(_.toSeq).toSeq) + + println(iarr1.concat(iarr2).toSeq) + println(iarr1.concat(List(8, 9)).toSeq) + println(iarr1.containsSlice(iarr2)) + println(iarr1.containsSlice(List(2, 3))) + + println(iarr1.corresponds(iarr2)(_ == _)) + println(iarr1.corresponds(List(1, 2, 3))(_ == _)) + println(iarr1.corresponds(List(2, 4, 6))(_ == 2 * _)) + + println(iarr1.diff(List(1, 2)).toSeq) + println(iarr1.diff(IArray(1, 2)).toSeq) + + println(iarr1.distinct.toSeq) + println(iarr2.distinct.toSeq) + println(iarr2.distinctBy(_ % 2 == 1).toSeq) + + println(iarr1.startsWith(IArray(2, 3))) + println(iarr1.startsWith(List(2, 3))) + println(iarr1.endsWith(IArray(2, 3))) + println(iarr1.endsWith(List(2, 3))) + println(iarr1.findLast(_ <= 1)) + println(iarr1.findLast(_ <= 2)) + + println(iarr1.fold(0)(_ + _)) + println(iarr1.foldLeft(0)(_ + _)) + println(iarr1.foldRight(0)(_ + _)) + + println(iarr1.reduce(_ + _)) + println(iarr1.reduceLeft(_ + _)) + println(iarr1.reduceRight(_ + _)) + + println(iarr1.groupBy(identity).mapValues(_.toSeq).toMap) + println(iarr1.groupBy(_ % 2).mapValues(_.toSeq).toMap) + + println(iarr1.groupMap(identity)(_.toString).mapValues(_.toSeq).toMap) + println(iarr1.groupMap(_ % 2)(_.toString).mapValues(_.toSeq).toMap) + + println(iarr1.groupMapReduce(identity)(_.toString)(_ + _).mapValues(_.toSeq).toMap) + println(iarr1.groupMapReduce(_ % 2)(_.toString)(_ + _).mapValues(_.toSeq).toMap) + + println(iarr1.grouped(2).map(_.toSeq).toList) + + println(iarr1.indexOfSlice(IArray(1, 2))) + println(iarr1.indexOfSlice(List(2, 3))) + println(iarr1.indexOfSlice(IArray(1, 2), 1)) + println(iarr1.indexOfSlice(List(2, 3), 1)) + println(iarr1.lastIndexOfSlice(IArray(1, 2))) + println(iarr1.lastIndexOfSlice(List(2, 3))) + println(iarr1.lastIndexOfSlice(IArray(1, 2), 1)) + println(iarr1.lastIndexOfSlice(List(2, 3), 1)) + + println(iarr1.inits.map(_.toSeq).toList) + println(iarr1.tails.map(_.toSeq).toList) + println(iarr1.intersect(List(1, 2)).toSeq) + println(iarr1.intersect(List(2, 3)).toSeq) + println(iarr1.isTraversableAgain) + println(iarr1.knownSize) + println(iarr1.lazyZip(iarr2)) + println(iarr1.lazyZip(iarr2.toSeq).toList) + println(iarr1.lengthCompare(3)) + println(iarr1.lengthCompare(1)) + println(iarr1.lengthCompare(4)) + + println(iarr1.max) + println(iarr1.maxOption) + println(iarr1.maxBy(identity)) + println(iarr1.maxByOption(identity)) + println(iarr1.min) + println(iarr1.minOption) + println(iarr1.minBy(identity)) + println(iarr1.minByOption(identity)) + + println(iarr1.mkString) + println(iarr1.mkString("-")) + println(iarr1.mkString("(", ",", ")")) + + println(iarr1.zip(iarr2.toSeq).toSeq) + println(iarr1.zip(Iterator(5, 5, 5)).toSeq) + println(iarr1.zipAll(IArray(5, 5), 3, 4).toSeq) + println(iarr1.zipAll(List(5, 5), 3, 4).toSeq) + + println(IArray((1, 'a'), (2, 'b')).unzip._1.toSeq) + println(IArray((1, 'a'), (2, 'b')).unzip._2.toSeq) + println(IArray((1, 'a', "x"), (2, 'b', "y")).unzip3._1.toSeq) + println(IArray((1, 'a', "x"), (2, 'b', "y")).unzip3._2.toSeq) + println(IArray((1, 'a', "x"), (2, 'b', "y")).unzip3._3.toSeq) + + println(iarr1.padTo(6, 0).toSeq) + println(iarr1.partitionMap[Int, Int](i => Left(i))._1.toSeq) + println(iarr1.partitionMap[Int, Int](i => Left(i))._2.toSeq) + println(iarr1.partitionMap[Int, Int](i => Right(i))._1.toSeq) + println(iarr1.partitionMap[Int, Int](i => Right(i))._2.toSeq) + println(iarr1.patch(1, List(6, 7, 8, 9), 2).toSeq) + println(iarr1.permutations.map(_.toSeq).toList) + + println(iarr1.sum) + println(iarr1.product) + + println(iarr1.iterator.toList) + println(iarr1.reverseIterator.toList) + + println(iarr1.sameElements(iarr1)) + println(iarr1.sameElements(iarr2.toSeq)) + + println(iarr1.segmentLength(_ < 2)) + println(iarr1.segmentLength(_ < 2, 1)) + + println(iarr1.sizeCompare(iarr2)) + println(iarr1.sizeCompare(iarr2.toSeq)) + println(iarr1.sizeCompare(1)) + + println(iarr1.sliding(2).map(_.toSeq).toList) + println(iarr2.sliding(3, 2).map(_.toSeq).toList) + + println(iarr2.sortBy(i => -i).toSeq) + + println(iarr1.startsWith(Iterator(1, 2), 0)) + println(iarr1.startsWith(Iterator(2, 3), 1)) + + println(iarr1.tapEach(x => println(x)).toSeq) + + println(iarr1.zipWithIndex.toSeq) + + println(iarr1.to(List)) + println(iarr1.to(Vector)) + println(iarr1.toBuffer) + println(iarr1.toIndexedSeq) + println(iarr1.toIterable) + println(iarr1.toList) + println(iarr1.toSet) + println(iarr1.toVector) + println(iarr1.view) + println(iarr1.zip(iarr2).toMap) + println(iarr1.zip(iarr2.toSeq).toMap) + + println(iarr1.empty) + println(iarr1.isTraversableAgain) + println(iarr1.lengthIs < 2) + println(iarr1.sizeIs < 2) + + iarr1.stepper + + println(IArray(List(1, 2), List(2, 3)).flatten.toSeq) + + println(iarr1.search(2)) + + println(iarr1.withFilter(_ != 2).map(identity).toSeq) + + for + x <- iarr1 + if x != 1 + y <- iarr2 + if y != 5 + if y != 65 + do + println((x, y)) + + println( + (for + x <- iarr1 + if x != 1 + y <- iarr2.toSeq + if y != 5 + if y != 65 + yield + (x, y) + ).toSeq) + + println(IArray[IArray[Int]]().transpose.map(_.toSeq).toSeq) + println(IArray(IArray(1, 2, 3), IArray(4, 5, 6)).transpose.map(_.toSeq).toSeq) + + println(IArray.equals(IArray("a"), IArray("b"))) + println(IArray.from(List("a", "b")).toSeq) + + val iab = IArray.newBuilder[Int] + iab += 1 + iab += 2 + iab.addOne(4) + iab.addAll(iarr1) + iab.addAll(Array(9)) + iab.addAll(Seq(10)) + println(iab.result().toSeq) + + + println( + (for + x <- List(1) + y <- iarr1 + y <- iarr2 + yield + (x, y) + ).toSeq) + + println( + (for + x1 <- List(1) + x2 <- IArray(true) + x3 <- IArray(1: Byte) + x4 <- IArray(2: Short) + x5 <- IArray(3) + x6 <- IArray(4L) + x7 <- IArray(5f) + x8 <- IArray(6d) + x9 <- IArray('a') + x10 <- IArray("abc") + x11 <- IArray("xyz": Any) + x12 <- IArray(()) + yield + (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) + ).toSeq) + + println( + (for + x1 <- IArray(1) + x2 <- IArray(true) + x3 <- IArray(1: Byte) + x4 <- IArray(2: Short) + x5 <- IArray(3) + x6 <- IArray(4L) + x7 <- IArray(5f) + x8 <- IArray(6d) + x9 <- IArray('a') + x10 <- IArray("abc") + x11 <- IArray("xyz": Any) + x12 <- IArray(()) + yield + (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) + ).toSeq) From 04ea0273aeaa8116958bf50e4f356dea24659441 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Feb 2021 09:24:57 +0100 Subject: [PATCH 02/10] Add converion from IArray to immutable.ArraySeq --- library/src/scala/IArray.scala | 129 ++++++--------------------------- 1 file changed, 22 insertions(+), 107 deletions(-) diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 9c06741e6863..1eb68c6bca07 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -254,9 +254,6 @@ object IArray: def :+ [U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr) :+ x def :++ [U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr) :++ suffix def :++ [U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr) :++ suffix - def addString(b: mutable.StringBuilder): mutable.StringBuilder = arr.toSeq.addString(b) - def addString(b: mutable.StringBuilder, sep: String): mutable.StringBuilder = arr.toSeq.addString(b, sep) - def addString(b: mutable.StringBuilder, start: String, sep: String, end: String): mutable.StringBuilder = arr.toSeq.addString(b, start, sep, end) def appended[U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr).appended(x) def appendedAll[U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr).appendedAll(suffix) def appendedAll[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr).appendedAll(suffix) @@ -265,89 +262,43 @@ object IArray: def combinations(n: Int): Iterator[IArray[T]] = genericArrayOps(arr).combinations(n) def concat[U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr).concat(suffix) def concat[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr).concat(suffix) - def containsSlice[U](that: IArray[U]): Boolean = arr.toSeq.containsSlice(that.toSeq) - def containsSlice[U](that: Seq[U]): Boolean = arr.toSeq.containsSlice(that) - def corresponds[U](that: IArray[U])(p: (T, U) => Boolean): Boolean = arr.toSeq.corresponds(that.toSeq)(p) - def corresponds[U](that: IterableOnce[U])(p: (T, U) => Boolean): Boolean = arr.toSeq.corresponds(that)(p) def diff[U >: T](that: IArray[U]): IArray[T] = genericArrayOps(arr).diff(that.toSeq) def diff[U >: T](that: Seq[U]): IArray[T] = genericArrayOps(arr).diff(that) def distinct: IArray[T] = genericArrayOps(arr).distinct def distinctBy[U](f: T => U): IArray[T] = genericArrayOps(arr).distinctBy(f) - def empty: immutable.ArraySeq[T] = arr.toSeq.empty def startsWith[U >: T](that: IArray[U]): Boolean = genericArrayOps(arr).startsWith(that, 0) def startsWith[U >: T](that: IArray[U], offset: Int): Boolean = genericArrayOps(arr).startsWith(that, offset) def startsWith[U >: T](that: IterableOnce[U]): Boolean = genericArrayOps(arr).startsWith(that, 0) def startsWith[U >: T](that: IterableOnce[U], offset: Int): Boolean = genericArrayOps(arr).startsWith(that, offset) def endsWith[U >: T](that: IArray[U]): Boolean = genericArrayOps(arr).endsWith(that) def endsWith[U >: T](that: Iterable[U]): Boolean = genericArrayOps(arr).endsWith(that) - def findLast(p: T => Boolean): Option[T] = arr.toSeq.findLast(p) def groupBy[K](f: T => K): immutable.Map[K, IArray[T]] = genericArrayOps(arr).groupBy(f) def groupMap[K, U: ClassTag](key: T => K)(f: T => U): immutable.Map[K, IArray[U]] = genericArrayOps(arr).groupMap(key)(f) - def groupMapReduce[K, U](key: (T) => K)(f: (T) => U)(reduce: (U, U) => U): immutable.Map[K, U] = arr.toSeq.groupMapReduce(key)(f)(reduce) def grouped(size: Int): Iterator[IArray[T]] = genericArrayOps(arr).grouped(size) - def indexOfSlice[U >: T](that: IArray[U]): Int = arr.toSeq.indexOfSlice(that) - def indexOfSlice[U >: T](that: Seq[U]): Int = arr.toSeq.indexOfSlice(that) - def indexOfSlice[U >: T](that: IArray[U], from: Int): Int = arr.toSeq.indexOfSlice(that, from) - def indexOfSlice[U >: T](that: Seq[U], from: Int): Int = arr.toSeq.indexOfSlice(that, from) def inits: Iterator[IArray[T]] = genericArrayOps(arr).inits def intersect[U >: T](that: IArray[U]): IArray[T] = genericArrayOps(arr).intersect(that) def intersect[U >: T](that: Seq[U]): IArray[T] = genericArrayOps(arr).intersect(that) - def isTraversableAgain: Boolean = arr.toSeq.isTraversableAgain - def knownSize: Int = arr.length - def lastIndexOfSlice[U >: T](that: IArray[U]): Int = arr.toSeq.lastIndexOfSlice(that) - def lastIndexOfSlice[U >: T](that: Seq[U]): Int = arr.toSeq.lastIndexOfSlice(that) - def lastIndexOfSlice[U >: T](that: IArray[U], end: Int): Int = arr.toSeq.lastIndexOfSlice(that, end) - def lastIndexOfSlice[U >: T](that: Seq[U], end: Int): Int = arr.toSeq.lastIndexOfSlice(that, end) def lazyZip[U](that: IArray[U]): LazyZip2[T, U, IArray[T]] = genericArrayOps(arr).lazyZip[U](that).asInstanceOf[LazyZip2[T, U, IArray[T]]] def lazyZip[U](that: Iterable[U]): LazyZip2[T, U, IArray[T]] = genericArrayOps(arr).lazyZip[U](that).asInstanceOf[LazyZip2[T, U, IArray[T]]] def lengthCompare(len: Int): Int = genericArrayOps(arr).lengthCompare(len) - def lengthIs: IterableOps.SizeCompareOps = arr.toSeq.lengthIs - def max[U >: T](using math.Ordering[U]): T = arr.toSeq.max[U] - def maxBy[U](f: T => U)(using math.Ordering[U]): T = arr.toSeq.maxBy(f) - def maxByOption[U](f: T => U)(using math.Ordering[U]): Option[T] = arr.toSeq.maxByOption(f) - def maxOption[U >: T](using math.Ordering[U]): Option[U] = arr.toSeq.maxOption[U] - def min[U >: T](using math.Ordering[U]): T = arr.toSeq.min[U] - def minBy[U](f: T => U)(using math.Ordering[U]): T = arr.toSeq.minBy(f) - def minByOption[U](f: T => U)(using math.Ordering[U]): Option[T] = arr.toSeq.minByOption(f) - def minOption[U >: T](using math.Ordering[U]): Option[U] = arr.toSeq.minOption[U] - def mkString: String = arr.toSeq.mkString - def mkString(sep: String): String = arr.toSeq.mkString(sep) - def mkString(start: String, sep: String, end: String): String = arr.toSeq.mkString(start, sep, end) def padTo[U >: T: ClassTag](len: Int, elem: U): IArray[U] = genericArrayOps(arr).padTo(len, elem) def partitionMap[T1: ClassTag, T2: ClassTag](f: T => Either[T1, T2]): (IArray[T1], IArray[T2]) = genericArrayOps(arr).partitionMap(f) def patch[U >: T: ClassTag](from: Int, other: IterableOnce[U], replaced: Int): IArray[U] = genericArrayOps(arr).patch(from, other, replaced) def permutations: Iterator[IArray[T]] = genericArrayOps(arr).permutations def prepended[U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr).prepended(x) def prependedAll[U >: T: ClassTag](prefix: IterableOnce[U]): IArray[U] = genericArrayOps(arr).prependedAll(prefix) - def product[U >: T](using math.Numeric[U]): U = arr.toSeq.product[U] - def reduce[U >: T](op: (U, U) => U): U = arr.toSeq.reduce(op) - def reduceLeft[U >: T](op: (U, T) => U): U = arr.toSeq.reduceLeft(op) - def reduceRight[U >: T](op: (T, U) => U): U = arr.toSeq.reduceRight(op) def reverseIterator: Iterator[T] = genericArrayOps(arr).reverseIterator - def sameElements[U >: T](that: IArray[U]): Boolean = arr.toSeq.sameElements(that) - def sameElements[U >: T](that: IterableOnce[U]): Boolean = arr.toSeq.sameElements(that) def search[U >: T](elem: U)(using Ordering[U]): Searching.SearchResult = arr.toSeq.search(elem) def search[U >: T](elem: U, from: Int, to: Int)(using Ordering[U]): Searching.SearchResult = arr.toSeq.search(elem, from, to) - def segmentLength(p: (T) => Boolean, from: Int): Int = arr.toSeq.segmentLength(p, from) - def segmentLength(p: (T) => Boolean): Int = arr.toSeq.segmentLength(p) def sizeCompare(that: IArray[Any]): Int = arr.toSeq.sizeCompare(that) def sizeCompare(that: Iterable[_]): Int = arr.toSeq.sizeCompare(that) def sizeCompare(otherSize: Int): Int = genericArrayOps(arr).sizeCompare(otherSize) - def sizeIs: IterableOps.SizeCompareOps = arr.toSeq.sizeIs def sliding(size: Int, step: Int = 1): Iterator[IArray[T]] = genericArrayOps(arr).sliding(size, step) def stepper[S <: Stepper[_]](using StepperShape[T, S]): S = genericArrayOps(arr).stepper[S] - def sum[U >: T](using math.Numeric[U]): U = arr.toSeq.sum[U] def tails: Iterator[IArray[T]] = genericArrayOps(arr).tails def tapEach[U](f: (T) => U): IArray[T] = arr.toSeq.foreach(f) arr - def to[C1](factory: Factory[T, C1]): C1 = arr.toSeq.to(factory) - def toBuffer[U >: T]: Buffer[U] = arr.toSeq.toBuffer[U] - def toIndexedSeq: immutable.IndexedSeq[T] = arr.toSeq.toIndexedSeq - def toIterable: Iterable[T] = arr.toSeq.toIterable - def toList: List[T] = arr.toSeq.toList - def toSet: Set[T] = arr.toSeq.toSet - def toVector: Vector[T] = arr.toSeq.toVector def unzip[T1, T2](using asPair: T => (T1, T2), ct1: ClassTag[T1], ct2: ClassTag[T2]): (IArray[T1], IArray[T2]) = genericArrayOps(arr).unzip def unzip3[T1, T2, T3](using asTriple: T => (T1, T2, T3), ct1: ClassTag[T1], ct2: ClassTag[T2], ct3: ClassTag[T3]): (IArray[T1], IArray[T2], IArray[T3]) = genericArrayOps(arr).unzip3 def updated[U >: T: ClassTag](index: Int, elem: U): IArray[U] = genericArrayOps(arr).updated(index, elem) @@ -373,85 +324,49 @@ object IArray: extension [T, U >: T: ClassTag](x: T) def +:(arr: IArray[U]): IArray[U] = genericArrayOps(arr).prepended(x) - extension [T1, T2](arr: IArray[(T1, T2)]) - def toMap: Map[T1, T2] = arr.toSeq.toMap - - /** Conversion from IArray to immutable.ArraySeq */ - extension [T](arr: IArray[T]) def toSeq: immutable.ArraySeq[T] = - immutable.ArraySeq.unsafeWrapArray(arr.asInstanceOf[Array[T]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension [T <: AnyRef](arr: IArray[T]) def toSeq: immutable.ArraySeq[T] = - immutable.ArraySeq.ofRef(arr.asInstanceOf[Array[T]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension (arr: IArray[Int]) def toSeq: immutable.ArraySeq[Int] = - immutable.ArraySeq.ofInt(arr.asInstanceOf[Array[Int]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension (arr: IArray[Double]) def toSeq: immutable.ArraySeq[Double] = - immutable.ArraySeq.ofDouble(arr.asInstanceOf[Array[Double]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension (arr: IArray[Long]) def toSeq: immutable.ArraySeq[Long] = - immutable.ArraySeq.ofLong(arr.asInstanceOf[Array[Long]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension (arr: IArray[Float]) def toSeq: immutable.ArraySeq[Float] = - immutable.ArraySeq.ofFloat(arr.asInstanceOf[Array[Float]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension (arr: IArray[Char]) def toSeq: immutable.ArraySeq[Char] = - immutable.ArraySeq.ofChar(arr.asInstanceOf[Array[Char]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension (arr: IArray[Byte]) def toSeq: immutable.ArraySeq[Byte] = - immutable.ArraySeq.ofByte(arr.asInstanceOf[Array[Byte]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension (arr: IArray[Short]) def toSeq: immutable.ArraySeq[Short] = - immutable.ArraySeq.ofShort(arr.asInstanceOf[Array[Short]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension (arr: IArray[Boolean]) def toSeq: immutable.ArraySeq[Boolean] = - immutable.ArraySeq.ofBoolean(arr.asInstanceOf[Array[Boolean]]) - - /** Conversion from IArray to immutable.ArraySeq */ - extension (arr: IArray[Unit]) def toSeq: immutable.ArraySeq[Unit] = - immutable.ArraySeq.ofUnit(arr.asInstanceOf[Array[Unit]]) - /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapIArray[T](using DummyImplicit): Conversion[IArray[T], immutable.ArraySeq[T]] = _.toSeq + given genericWrapIArray[T](using DummyImplicit): Conversion[IArray[T], scala.collection.immutable.ArraySeq[T]] = + arr => scala.collection.immutable.ArraySeq.unsafeWrapArray(arr.asInstanceOf[Array[T]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapAnyRefIArray[T <: AnyRef](using DummyImplicit): Conversion[IArray[T], immutable.ArraySeq[T]] = _.toSeq + given genericWrapAnyRefIArray[T <: AnyRef](using DummyImplicit): Conversion[IArray[T], scala.collection.immutable.ArraySeq[T]] = + arr => scala.collection.immutable.ArraySeq.ofRef(arr.asInstanceOf[Array[T]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapIntIArray(using DummyImplicit): Conversion[IArray[Int], immutable.ArraySeq[Int]] = _.toSeq + given genericWrapIntIArray(using DummyImplicit): Conversion[IArray[Int], scala.collection.immutable.ArraySeq[Int]] = + arr => scala.collection.immutable.ArraySeq.ofInt(arr.asInstanceOf[Array[Int]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapDoubleIArray(using DummyImplicit): Conversion[IArray[Double], immutable.ArraySeq[Double]] = _.toSeq + given genericWrapDoubleIArray(using DummyImplicit): Conversion[IArray[Double], scala.collection.immutable.ArraySeq[Double]] = + arr => scala.collection.immutable.ArraySeq.ofDouble(arr.asInstanceOf[Array[Double]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapLongIArray(using DummyImplicit): Conversion[IArray[Long], immutable.ArraySeq[Long]] = _.toSeq + given genericWrapLongIArray(using DummyImplicit): Conversion[IArray[Long], scala.collection.immutable.ArraySeq[Long]] = + arr => scala.collection.immutable.ArraySeq.ofLong(arr.asInstanceOf[Array[Long]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapFloatIArray(using DummyImplicit): Conversion[IArray[Float], immutable.ArraySeq[Float]] = _.toSeq + given genericWrapFloatIArray(using DummyImplicit): Conversion[IArray[Float], scala.collection.immutable.ArraySeq[Float]] = + arr => scala.collection.immutable.ArraySeq.ofFloat(arr.asInstanceOf[Array[Float]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapCharIArray(using DummyImplicit): Conversion[IArray[Char], immutable.ArraySeq[Char]] = _.toSeq + given genericWrapCharIArray(using DummyImplicit): Conversion[IArray[Char], scala.collection.immutable.ArraySeq[Char]] = + arr => scala.collection.immutable.ArraySeq.ofChar(arr.asInstanceOf[Array[Char]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapByteIArray(using DummyImplicit): Conversion[IArray[Byte], immutable.ArraySeq[Byte]] = _.toSeq + given genericWrapByteIArray(using DummyImplicit): Conversion[IArray[Byte], scala.collection.immutable.ArraySeq[Byte]] = + arr => scala.collection.immutable.ArraySeq.ofByte(arr.asInstanceOf[Array[Byte]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapShortIArray(using DummyImplicit): Conversion[IArray[Short], immutable.ArraySeq[Short]] = _.toSeq + given genericWrapShortIArray(using DummyImplicit): Conversion[IArray[Short], scala.collection.immutable.ArraySeq[Short]] = + arr => scala.collection.immutable.ArraySeq.ofShort(arr.asInstanceOf[Array[Short]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapBooleanIArray(using DummyImplicit): Conversion[IArray[Boolean], immutable.ArraySeq[Boolean]] = _.toSeq + given genericWrapBooleanIArray(using DummyImplicit): Conversion[IArray[Boolean], scala.collection.immutable.ArraySeq[Boolean]] = + arr => scala.collection.immutable.ArraySeq.ofBoolean(arr.asInstanceOf[Array[Boolean]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapUnitIArray(using DummyImplicit): Conversion[IArray[Unit], immutable.ArraySeq[Unit]] = _.toSeq + given genericWrapUnitIArray(using DummyImplicit): Conversion[IArray[Unit], scala.collection.immutable.ArraySeq[Unit]] = + arr => scala.collection.immutable.ArraySeq.ofUnit(arr.asInstanceOf[Array[Unit]]) /** Convert an array into an immutable array without copying, the original array * must _not_ be mutated after this or the guaranteed immutablity of IArray will From 8136b5c40d194f7eda90249927204d00d5625295 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Feb 2021 11:52:06 +0100 Subject: [PATCH 03/10] Add comments --- library/src/scala/IArray.scala | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 1eb68c6bca07..213563a80b29 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -131,6 +131,9 @@ object IArray: /** Finds index of first occurrence of some value in this array after or at some start index. */ extension [T](arr: IArray[T]) def indexOf(elem: T, from: Int = 0): Int = + // `asInstanceOf` needed because `elem` does not have type `arr.T` + // We could use `arr.iterator.indexOf(elem, from)` or `arr.indexWhere(_ == elem, from)` + // but these would incur some overhead. genericArrayOps(arr).indexOf(elem.asInstanceOf, from) /** Finds index of the first element satisfying some predicate after or at some start index. */ @@ -163,6 +166,7 @@ object IArray: /** Finds index of last occurrence of some value in this array before or at a given end index. */ extension [T](arr: IArray[T]) def lastIndexOf(elem: T, end: Int = arr.length - 1): Int = + // see: same issue in `indexOf` genericArrayOps(arr).lastIndexOf(elem.asInstanceOf, end) /** Finds index of last element satisfying some predicate before or at given end index. */ @@ -299,6 +303,8 @@ object IArray: def tapEach[U](f: (T) => U): IArray[T] = arr.toSeq.foreach(f) arr + def transpose[U](implicit asArray: T => IArray[U]): IArray[IArray[U]] = + genericArrayOps(arr).transpose(using asArray.asInstanceOf[T => Array[U]]) def unzip[T1, T2](using asPair: T => (T1, T2), ct1: ClassTag[T1], ct2: ClassTag[T2]): (IArray[T1], IArray[T2]) = genericArrayOps(arr).unzip def unzip3[T1, T2, T3](using asTriple: T => (T1, T2, T3), ct1: ClassTag[T1], ct2: ClassTag[T2], ct3: ClassTag[T3]): (IArray[T1], IArray[T2], IArray[T3]) = genericArrayOps(arr).unzip3 def updated[U >: T: ClassTag](index: Int, elem: U): IArray[U] = genericArrayOps(arr).updated(index, elem) @@ -309,11 +315,6 @@ object IArray: def zipAll[T1 >: T, U](that: IArray[U], thisElem: T1, thatElem: U): IArray[(T1, U)] = genericArrayOps(arr).zipAll(that, thisElem, thatElem) def zipAll[T1 >: T, U](that: Iterable[U], thisElem: T1, thatElem: U): IArray[(T1, U)] = genericArrayOps(arr).zipAll(that, thisElem, thatElem) def zipWithIndex: IArray[(T, Int)] = genericArrayOps(arr).zipWithIndex - end extension - - extension [T](arr: IArray[T]) - def transpose[U](implicit asArray: T => IArray[U]): IArray[IArray[U]] = - genericArrayOps(arr).transpose(using asArray.asInstanceOf[T => Array[U]]) extension [T, U >: T: ClassTag](prefix: IterableOnce[T]) def ++:(arr: IArray[U]): IArray[U] = genericArrayOps(arr).prependedAll(prefix) @@ -442,6 +443,9 @@ object IArray: * @return the array created from concatenating `xss` */ def concat[T: ClassTag](xss: IArray[T]*): IArray[T] = + // `Array.concat` should arguably take in a `Seq[Array[_ <: T]]`, + // but since it currently takes a `Seq[Array[T]]` we have to perform a cast, + // knowing tacitly that `concat` is not going to do the wrong thing. Array.concat[T](xss.asInstanceOf[immutable.Seq[Array[T]]]: _*) /** Returns an immutable array that contains the results of some element computation a number From a55b18c823fb0bc14096265318ce13c444e24fab Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Feb 2021 13:10:33 +0100 Subject: [PATCH 04/10] Delegate implementation of IArrayBuilder to ArrayBuilder --- library/src/scala/IArray.scala | 422 ++++----------------------------- 1 file changed, 51 insertions(+), 371 deletions(-) diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 213563a80b29..240e52fb9d4b 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -2,7 +2,7 @@ package scala import reflect.ClassTag import scala.collection._ -import scala.collection.mutable.Buffer +import scala.collection.mutable.ArrayBuilder opaque type IArray[+T] = Array[_ <: T] @@ -674,54 +674,25 @@ object IArray: sealed abstract class IArrayBuilder[T] extends mutable.ReusableBuilder[T, IArray[T]] with Serializable { - protected[this] var capacity: Int = 0 - protected[this] def elems: Array[T] - protected var size: Int = 0 - def length: Int = size + protected[this] val arrayBuilder: ArrayBuilder[T] - override def knownSize: Int = size - - protected[this] final def ensureSize(size: Int): Unit = { - if (capacity < size || capacity == 0) { - var newsize = if (capacity == 0) 16 else capacity * 2 - while (newsize < size) newsize *= 2 - resize(newsize) - } - } - - override final def sizeHint(size: Int): Unit = - if (capacity < size) resize(size) - - def clear(): Unit = size = 0 - - protected[this] def resize(size: Int): Unit + override final def sizeHint(size: Int): Unit = arrayBuilder.sizeHint(size) + def clear(): Unit = arrayBuilder.clear() /** Add all elements of an array */ - def addAll(xs: IArray[T]): this.type = addAll(xs, 0, xs.length) + def addAll(xs: IArray[T]): this.type = + arrayBuilder.addAll(xs.asInstanceOf[Array[T]]) + this /** Add a slice of an array */ - def addAll(xs: IArray[T], offset: Int, length: Int): this.type = { - ensureSize(this.size + length) - Array.copy(xs.asInstanceOf[Array[T]], offset, elems, this.size, length) - size += length + def addAll(xs: IArray[T], offset: Int, length: Int): this.type = + arrayBuilder.addAll(xs.asInstanceOf[Array[T]], offset, length) this - } - override def addAll(xs: IterableOnce[T]): this.type = { - val k = xs.knownSize - if (k > 0) { - ensureSize(this.size + k) - // IterableOnce.copyElemsToArray(xs, elems, this.size) - // manually inlined as - xs match { - case src: Iterable[T] => src.copyToArray[T](elems, this.size, Int.MaxValue) - case src => src.iterator.copyToArray[T](elems, this.size, Int.MaxValue) - } - size += k - } else if (k < 0) super.addAll(xs) + override def addAll(xs: IterableOnce[T]): this.type = + arrayBuilder.addAll(xs) this - } } /** A companion object for array builders. @@ -757,421 +728,130 @@ object IArray: */ @SerialVersionUID(3L) final class ofRef[T <: AnyRef](implicit ct: ClassTag[T]) extends IArrayBuilder[T] { - - protected var elems: Array[T] = _ - - private def mkArray(size: Int): Array[T] = { - if (capacity == this.size && capacity > 0) elems - else if (elems eq null) new Array[T](size) - else java.util.Arrays.copyOf[T](elems, size) - } - - protected[this] def resize(size: Int): Unit = { - elems = mkArray(size) - capacity = size - } - - def addOne(elem: T): this.type = { - ensureSize(this.size + 1) - elems(this.size) = elem - this.size += 1 - this - } - - def result(): IArray[T] = { - if (capacity != 0 && capacity == this.size) { - capacity = 0 - val res = elems - elems = null - IArray.unsafeFromArray(res) - } - else IArray.unsafeFromArray(mkArray(this.size)) - } - - override def clear(): Unit = { - super.clear() - if(elems ne null) java.util.Arrays.fill(elems.asInstanceOf[Array[AnyRef]], null) - } - + protected[this] val arrayBuilder: ArrayBuilder[T] = new ArrayBuilder.ofRef + def addOne(elem: T): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[T] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofRef[_] => (this.size == x.size) && (elems == x.elems) + case x: ofRef[_] => this.arrayBuilder == x.arrayBuilder case _ => false } - override def toString = "IArrayBuilder.ofRef" } /** A class for array builders for arrays of `byte`s. It can be reused. */ @SerialVersionUID(3L) final class ofByte extends IArrayBuilder[Byte] { - - protected var elems: Array[Byte] = _ - - private def mkArray(size: Int): Array[Byte] = { - val newelems = new Array[Byte](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems - } - - protected[this] def resize(size: Int): Unit = { - elems = mkArray(size) - capacity = size - } - - def addOne(elem: Byte): this.type = { - ensureSize(this.size + 1) - elems(this.size) = elem - this.size += 1 - this - } - - def result(): IArray[Byte] = { - if (capacity != 0 && capacity == this.size) { - capacity = 0 - val res = elems - elems = null - IArray.unsafeFromArray(res) - } - else IArray.unsafeFromArray(mkArray(this.size)) - } - + protected[this] val arrayBuilder: ArrayBuilder[Byte] = new ArrayBuilder.ofByte + def addOne(elem: Byte): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Byte] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofByte => (this.size == x.size) && (elems == x.elems) + case x: ofByte => this.arrayBuilder == x.arrayBuilder case _ => false } - override def toString = "IArrayBuilder.ofByte" } /** A class for array builders for arrays of `short`s. It can be reused. */ @SerialVersionUID(3L) final class ofShort extends IArrayBuilder[Short] { - - protected var elems: Array[Short] = _ - - private def mkArray(size: Int): Array[Short] = { - val newelems = new Array[Short](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems - } - - protected[this] def resize(size: Int): Unit = { - elems = mkArray(size) - capacity = size - } - - def addOne(elem: Short): this.type = { - ensureSize(this.size + 1) - elems(this.size) = elem - this.size += 1 - this - } - - def result(): IArray[Short] = { - if (capacity != 0 && capacity == this.size) { - capacity = 0 - val res = elems - elems = null - IArray.unsafeFromArray(res) - } - else IArray.unsafeFromArray(mkArray(this.size)) - } - + protected[this] val arrayBuilder: ArrayBuilder[Short] = new ArrayBuilder.ofShort + def addOne(elem: Short): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Short] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofShort => (this.size == x.size) && (elems == x.elems) + case x: ofShort => this.arrayBuilder == x.arrayBuilder case _ => false } - override def toString = "IArrayBuilder.ofShort" } /** A class for array builders for arrays of `char`s. It can be reused. */ @SerialVersionUID(3L) final class ofChar extends IArrayBuilder[Char] { - - protected var elems: Array[Char] = _ - - private def mkArray(size: Int): Array[Char] = { - val newelems = new Array[Char](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems - } - - protected[this] def resize(size: Int): Unit = { - elems = mkArray(size) - capacity = size - } - - def addOne(elem: Char): this.type = { - ensureSize(this.size + 1) - elems(this.size) = elem - this.size += 1 - this - } - - def result(): IArray[Char] = { - if (capacity != 0 && capacity == this.size) { - capacity = 0 - val res = elems - elems = null - IArray.unsafeFromArray(res) - } - else IArray.unsafeFromArray(mkArray(this.size)) - } - + protected[this] val arrayBuilder: ArrayBuilder[Char] = new ArrayBuilder.ofChar + def addOne(elem: Char): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Char] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofChar => (this.size == x.size) && (elems == x.elems) + case x: ofChar => this.arrayBuilder == x.arrayBuilder case _ => false } - override def toString = "IArrayBuilder.ofChar" } /** A class for array builders for arrays of `int`s. It can be reused. */ @SerialVersionUID(3L) final class ofInt extends IArrayBuilder[Int] { - - protected var elems: Array[Int] = _ - - private def mkArray(size: Int): Array[Int] = { - val newelems = new Array[Int](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems - } - - protected[this] def resize(size: Int): Unit = { - elems = mkArray(size) - capacity = size - } - - def addOne(elem: Int): this.type = { - ensureSize(this.size + 1) - elems(this.size) = elem - this.size += 1 - this - } - - def result(): IArray[Int] = { - if (capacity != 0 && capacity == this.size) { - capacity = 0 - val res = elems - elems = null - IArray.unsafeFromArray(res) - } - else IArray.unsafeFromArray(mkArray(this.size)) - } - + protected[this] val arrayBuilder: ArrayBuilder[Int] = new ArrayBuilder.ofInt + def addOne(elem: Int): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Int] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofInt => (this.size == x.size) && (elems == x.elems) + case x: ofInt => this.arrayBuilder == x.arrayBuilder case _ => false } - override def toString = "IArrayBuilder.ofInt" } /** A class for array builders for arrays of `long`s. It can be reused. */ @SerialVersionUID(3L) final class ofLong extends IArrayBuilder[Long] { - - protected var elems: Array[Long] = _ - - private def mkArray(size: Int): Array[Long] = { - val newelems = new Array[Long](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems - } - - protected[this] def resize(size: Int): Unit = { - elems = mkArray(size) - capacity = size - } - - def addOne(elem: Long): this.type = { - ensureSize(this.size + 1) - elems(this.size) = elem - this.size += 1 - this - } - - def result(): IArray[Long] = { - if (capacity != 0 && capacity == this.size) { - capacity = 0 - val res = elems - elems = null - IArray.unsafeFromArray(res) - } - else IArray.unsafeFromArray(mkArray(this.size)) - } - + protected[this] val arrayBuilder: ArrayBuilder[Long] = new ArrayBuilder.ofLong + def addOne(elem: Long): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Long] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofLong => (this.size == x.size) && (elems == x.elems) + case x: ofLong => this.arrayBuilder == x.arrayBuilder case _ => false } - override def toString = "IArrayBuilder.ofLong" } /** A class for array builders for arrays of `float`s. It can be reused. */ @SerialVersionUID(3L) final class ofFloat extends IArrayBuilder[Float] { - - protected var elems: Array[Float] = _ - - private def mkArray(size: Int): Array[Float] = { - val newelems = new Array[Float](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems - } - - protected[this] def resize(size: Int): Unit = { - elems = mkArray(size) - capacity = size - } - - def addOne(elem: Float): this.type = { - ensureSize(this.size + 1) - elems(this.size) = elem - this.size += 1 - this - } - - def result(): IArray[Float] = { - if (capacity != 0 && capacity == this.size) { - capacity = 0 - val res = elems - elems = null - IArray.unsafeFromArray(res) - } - else IArray.unsafeFromArray(mkArray(this.size)) - } - + protected[this] val arrayBuilder: ArrayBuilder[Float] = new ArrayBuilder.ofFloat + def addOne(elem: Float): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Float] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofFloat => (this.size == x.size) && (elems == x.elems) + case x: ofFloat => this.arrayBuilder == x.arrayBuilder case _ => false } - override def toString = "IArrayBuilder.ofFloat" } /** A class for array builders for arrays of `double`s. It can be reused. */ @SerialVersionUID(3L) final class ofDouble extends IArrayBuilder[Double] { - - protected var elems: Array[Double] = _ - - private def mkArray(size: Int): Array[Double] = { - val newelems = new Array[Double](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems - } - - protected[this] def resize(size: Int): Unit = { - elems = mkArray(size) - capacity = size - } - - def addOne(elem: Double): this.type = { - ensureSize(this.size + 1) - elems(this.size) = elem - this.size += 1 - this - } - - def result(): IArray[Double] = { - if (capacity != 0 && capacity == this.size) { - capacity = 0 - val res = elems - elems = null - IArray.unsafeFromArray(res) - } - else IArray.unsafeFromArray(mkArray(this.size)) - } - + protected[this] val arrayBuilder: ArrayBuilder[Double] = new ArrayBuilder.ofDouble + def addOne(elem: Double): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Double] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofDouble => (this.size == x.size) && (elems == x.elems) + case x: ofDouble => this.arrayBuilder == x.arrayBuilder case _ => false } - override def toString = "IArrayBuilder.ofDouble" } /** A class for array builders for arrays of `boolean`s. It can be reused. */ @SerialVersionUID(3L) class ofBoolean extends IArrayBuilder[Boolean] { - - protected var elems: Array[Boolean] = _ - - private def mkArray(size: Int): Array[Boolean] = { - val newelems = new Array[Boolean](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems - } - - protected[this] def resize(size: Int): Unit = { - elems = mkArray(size) - capacity = size - } - - def addOne(elem: Boolean): this.type = { - ensureSize(this.size + 1) - elems(this.size) = elem - this.size += 1 - this - } - - def result(): IArray[Boolean] = { - if (capacity != 0 && capacity == this.size) { - capacity = 0 - val res = elems - elems = null - IArray.unsafeFromArray(res) - } - else IArray.unsafeFromArray(mkArray(this.size)) - } - + protected[this] val arrayBuilder: ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean + def addOne(elem: Boolean): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Boolean] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofBoolean => (this.size == x.size) && (elems == x.elems) + case x: ofBoolean => this.arrayBuilder == x.arrayBuilder case _ => false } - override def toString = "IArrayBuilder.ofBoolean" } /** A class for array builders for arrays of `Unit` type. It can be reused. */ @SerialVersionUID(3L) final class ofUnit extends IArrayBuilder[Unit] { - - protected def elems: Array[Unit] = throw new UnsupportedOperationException() - - def addOne(elem: Unit): this.type = { - this.size += 1 - this - } - - override def addAll(xs: IterableOnce[Unit]): this.type = { - this.size += xs.iterator.size - this - } - - override def addAll(xs: IArray[Unit], offset: Int, length: Int): this.type = { - this.size += length - this - } - - def result(): IArray[Unit] = { - val ans = new Array[Unit](this.size) - var i = 0 - while (i < this.size) { ans(i) = (); i += 1 } - IArray.unsafeFromArray(ans) - } - + protected[this] val arrayBuilder: ArrayBuilder[Unit] = new ArrayBuilder.ofUnit + def addOne(elem: Unit): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Unit] = IArray.unsafeFromArray(arrayBuilder.result()) override def equals(other: Any): Boolean = other match { - case x: ofUnit => (this.size == x.size) + case x: ofUnit => this.arrayBuilder == x.arrayBuilder case _ => false } - - protected[this] def resize(size: Int): Unit = () - override def toString = "IArrayBuilder.ofUnit" } } From b26da403eb48f5f46afc5359f0c37a0237c8a067 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Feb 2021 13:16:23 +0100 Subject: [PATCH 05/10] Move IArrayBuilder to scala.collection.mutable --- library/src/scala/IArray.scala | 192 +----------------- .../collection/mutable/IArrayBuilder.scala | 192 ++++++++++++++++++ 2 files changed, 193 insertions(+), 191 deletions(-) create mode 100644 library/src/scala/collection/mutable/IArrayBuilder.scala diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 240e52fb9d4b..63c409528ca1 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -2,7 +2,7 @@ package scala import reflect.ClassTag import scala.collection._ -import scala.collection.mutable.ArrayBuilder +import scala.collection.mutable.IArrayBuilder opaque type IArray[+T] = Array[_ <: T] @@ -666,194 +666,4 @@ object IArray: end WithFilter - /** A builder class for immutable arrays. - * - * @tparam T the type of the elements for the builder. - */ - @SerialVersionUID(3L) - sealed abstract class IArrayBuilder[T] - extends mutable.ReusableBuilder[T, IArray[T]] - with Serializable { - - protected[this] val arrayBuilder: ArrayBuilder[T] - - override final def sizeHint(size: Int): Unit = arrayBuilder.sizeHint(size) - def clear(): Unit = arrayBuilder.clear() - - /** Add all elements of an array */ - def addAll(xs: IArray[T]): this.type = - arrayBuilder.addAll(xs.asInstanceOf[Array[T]]) - this - - /** Add a slice of an array */ - def addAll(xs: IArray[T], offset: Int, length: Int): this.type = - arrayBuilder.addAll(xs.asInstanceOf[Array[T]], offset, length) - this - - override def addAll(xs: IterableOnce[T]): this.type = - arrayBuilder.addAll(xs) - this - } - - /** A companion object for array builders. - */ - object IArrayBuilder { - - /** Creates a new arraybuilder of type `T`. - * - * @tparam T type of the elements for the array builder, with a `ClassTag` context bound. - * @return a new empty array builder. - */ - @inline def make[T: ClassTag]: IArrayBuilder[T] = { - val tag = implicitly[ClassTag[T]] - tag.runtimeClass match { - case java.lang.Byte.TYPE => new IArrayBuilder.ofByte().asInstanceOf[IArrayBuilder[T]] - case java.lang.Short.TYPE => new IArrayBuilder.ofShort().asInstanceOf[IArrayBuilder[T]] - case java.lang.Character.TYPE => new IArrayBuilder.ofChar().asInstanceOf[IArrayBuilder[T]] - case java.lang.Integer.TYPE => new IArrayBuilder.ofInt().asInstanceOf[IArrayBuilder[T]] - case java.lang.Long.TYPE => new IArrayBuilder.ofLong().asInstanceOf[IArrayBuilder[T]] - case java.lang.Float.TYPE => new IArrayBuilder.ofFloat().asInstanceOf[IArrayBuilder[T]] - case java.lang.Double.TYPE => new IArrayBuilder.ofDouble().asInstanceOf[IArrayBuilder[T]] - case java.lang.Boolean.TYPE => new IArrayBuilder.ofBoolean().asInstanceOf[IArrayBuilder[T]] - case java.lang.Void.TYPE => new IArrayBuilder.ofUnit().asInstanceOf[IArrayBuilder[T]] - case _ => new IArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[IArrayBuilder[T]] - } - } - - /** A class for array builders for arrays of reference types. - * - * This builder can be reused. - * - * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassTag` context bound. - */ - @SerialVersionUID(3L) - final class ofRef[T <: AnyRef](implicit ct: ClassTag[T]) extends IArrayBuilder[T] { - protected[this] val arrayBuilder: ArrayBuilder[T] = new ArrayBuilder.ofRef - def addOne(elem: T): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[T] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofRef[_] => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofRef" - } - - /** A class for array builders for arrays of `byte`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofByte extends IArrayBuilder[Byte] { - protected[this] val arrayBuilder: ArrayBuilder[Byte] = new ArrayBuilder.ofByte - def addOne(elem: Byte): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Byte] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofByte => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofByte" - } - - /** A class for array builders for arrays of `short`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofShort extends IArrayBuilder[Short] { - protected[this] val arrayBuilder: ArrayBuilder[Short] = new ArrayBuilder.ofShort - def addOne(elem: Short): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Short] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofShort => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofShort" - } - - /** A class for array builders for arrays of `char`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofChar extends IArrayBuilder[Char] { - protected[this] val arrayBuilder: ArrayBuilder[Char] = new ArrayBuilder.ofChar - def addOne(elem: Char): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Char] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofChar => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofChar" - } - - /** A class for array builders for arrays of `int`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofInt extends IArrayBuilder[Int] { - protected[this] val arrayBuilder: ArrayBuilder[Int] = new ArrayBuilder.ofInt - def addOne(elem: Int): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Int] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofInt => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofInt" - } - - /** A class for array builders for arrays of `long`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofLong extends IArrayBuilder[Long] { - protected[this] val arrayBuilder: ArrayBuilder[Long] = new ArrayBuilder.ofLong - def addOne(elem: Long): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Long] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofLong => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofLong" - } - - /** A class for array builders for arrays of `float`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofFloat extends IArrayBuilder[Float] { - protected[this] val arrayBuilder: ArrayBuilder[Float] = new ArrayBuilder.ofFloat - def addOne(elem: Float): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Float] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofFloat => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofFloat" - } - - /** A class for array builders for arrays of `double`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofDouble extends IArrayBuilder[Double] { - protected[this] val arrayBuilder: ArrayBuilder[Double] = new ArrayBuilder.ofDouble - def addOne(elem: Double): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Double] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofDouble => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofDouble" - } - - /** A class for array builders for arrays of `boolean`s. It can be reused. */ - @SerialVersionUID(3L) - class ofBoolean extends IArrayBuilder[Boolean] { - protected[this] val arrayBuilder: ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean - def addOne(elem: Boolean): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Boolean] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofBoolean => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofBoolean" - } - - /** A class for array builders for arrays of `Unit` type. It can be reused. */ - @SerialVersionUID(3L) - final class ofUnit extends IArrayBuilder[Unit] { - protected[this] val arrayBuilder: ArrayBuilder[Unit] = new ArrayBuilder.ofUnit - def addOne(elem: Unit): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Unit] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofUnit => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofUnit" - } - } - end IArray diff --git a/library/src/scala/collection/mutable/IArrayBuilder.scala b/library/src/scala/collection/mutable/IArrayBuilder.scala new file mode 100644 index 000000000000..254c735e2ecc --- /dev/null +++ b/library/src/scala/collection/mutable/IArrayBuilder.scala @@ -0,0 +1,192 @@ +package scala.collection.mutable + +import scala.reflect.ClassTag + +/** A builder class for immutable arrays. + * + * @tparam T the type of the elements for the builder. + */ +@SerialVersionUID(3L) +sealed abstract class IArrayBuilder[T] + extends ReusableBuilder[T, IArray[T]] + with Serializable { + + protected[this] val arrayBuilder: ArrayBuilder[T] + + override final def sizeHint(size: Int): Unit = arrayBuilder.sizeHint(size) + def clear(): Unit = arrayBuilder.clear() + + /** Add all elements of an array */ + def addAll(xs: IArray[T]): this.type = + arrayBuilder.addAll(xs.asInstanceOf[Array[T]]) + this + + /** Add a slice of an array */ + def addAll(xs: IArray[T], offset: Int, length: Int): this.type = + arrayBuilder.addAll(xs.asInstanceOf[Array[T]], offset, length) + this + + override def addAll(xs: IterableOnce[T]): this.type = + arrayBuilder.addAll(xs) + this +} + +/** A companion object for array builders. */ +object IArrayBuilder { + + /** Creates a new arraybuilder of type `T`. + * + * @tparam T type of the elements for the array builder, with a `ClassTag` context bound. + * @return a new empty array builder. + */ + @inline def make[T: ClassTag]: IArrayBuilder[T] = { + val tag = implicitly[ClassTag[T]] + tag.runtimeClass match { + case java.lang.Byte.TYPE => new IArrayBuilder.ofByte().asInstanceOf[IArrayBuilder[T]] + case java.lang.Short.TYPE => new IArrayBuilder.ofShort().asInstanceOf[IArrayBuilder[T]] + case java.lang.Character.TYPE => new IArrayBuilder.ofChar().asInstanceOf[IArrayBuilder[T]] + case java.lang.Integer.TYPE => new IArrayBuilder.ofInt().asInstanceOf[IArrayBuilder[T]] + case java.lang.Long.TYPE => new IArrayBuilder.ofLong().asInstanceOf[IArrayBuilder[T]] + case java.lang.Float.TYPE => new IArrayBuilder.ofFloat().asInstanceOf[IArrayBuilder[T]] + case java.lang.Double.TYPE => new IArrayBuilder.ofDouble().asInstanceOf[IArrayBuilder[T]] + case java.lang.Boolean.TYPE => new IArrayBuilder.ofBoolean().asInstanceOf[IArrayBuilder[T]] + case java.lang.Void.TYPE => new IArrayBuilder.ofUnit().asInstanceOf[IArrayBuilder[T]] + case _ => new IArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[IArrayBuilder[T]] + } + } + + /** A class for array builders for arrays of reference types. + * + * This builder can be reused. + * + * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassTag` context bound. + */ + @SerialVersionUID(3L) + final class ofRef[T <: AnyRef](implicit ct: ClassTag[T]) extends IArrayBuilder[T] { + protected[this] val arrayBuilder: ArrayBuilder[T] = new ArrayBuilder.ofRef + def addOne(elem: T): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[T] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofRef[_] => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofRef" + } + + /** A class for array builders for arrays of `byte`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofByte extends IArrayBuilder[Byte] { + protected[this] val arrayBuilder: ArrayBuilder[Byte] = new ArrayBuilder.ofByte + def addOne(elem: Byte): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Byte] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofByte => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofByte" + } + + /** A class for array builders for arrays of `short`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofShort extends IArrayBuilder[Short] { + protected[this] val arrayBuilder: ArrayBuilder[Short] = new ArrayBuilder.ofShort + def addOne(elem: Short): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Short] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofShort => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofShort" + } + + /** A class for array builders for arrays of `char`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofChar extends IArrayBuilder[Char] { + protected[this] val arrayBuilder: ArrayBuilder[Char] = new ArrayBuilder.ofChar + def addOne(elem: Char): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Char] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofChar => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofChar" + } + + /** A class for array builders for arrays of `int`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofInt extends IArrayBuilder[Int] { + protected[this] val arrayBuilder: ArrayBuilder[Int] = new ArrayBuilder.ofInt + def addOne(elem: Int): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Int] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofInt => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofInt" + } + + /** A class for array builders for arrays of `long`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofLong extends IArrayBuilder[Long] { + protected[this] val arrayBuilder: ArrayBuilder[Long] = new ArrayBuilder.ofLong + def addOne(elem: Long): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Long] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofLong => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofLong" + } + + /** A class for array builders for arrays of `float`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofFloat extends IArrayBuilder[Float] { + protected[this] val arrayBuilder: ArrayBuilder[Float] = new ArrayBuilder.ofFloat + def addOne(elem: Float): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Float] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofFloat => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofFloat" + } + + /** A class for array builders for arrays of `double`s. It can be reused. */ + @SerialVersionUID(3L) + final class ofDouble extends IArrayBuilder[Double] { + protected[this] val arrayBuilder: ArrayBuilder[Double] = new ArrayBuilder.ofDouble + def addOne(elem: Double): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Double] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofDouble => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofDouble" + } + + /** A class for array builders for arrays of `boolean`s. It can be reused. */ + @SerialVersionUID(3L) + class ofBoolean extends IArrayBuilder[Boolean] { + protected[this] val arrayBuilder: ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean + def addOne(elem: Boolean): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Boolean] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofBoolean => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofBoolean" + } + + /** A class for array builders for arrays of `Unit` type. It can be reused. */ + @SerialVersionUID(3L) + final class ofUnit extends IArrayBuilder[Unit] { + protected[this] val arrayBuilder: ArrayBuilder[Unit] = new ArrayBuilder.ofUnit + def addOne(elem: Unit): this.type = { arrayBuilder.addOne(elem); this } + def result(): IArray[Unit] = IArray.unsafeFromArray(arrayBuilder.result()) + override def equals(other: Any): Boolean = other match { + case x: ofUnit => this.arrayBuilder == x.arrayBuilder + case _ => false + } + override def toString = "IArrayBuilder.ofUnit" + } +} From ad7ab97174f9981b103c48bb2c8834560f7aca52 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Feb 2021 14:39:25 +0100 Subject: [PATCH 06/10] Use implicit defs for conversions to avoid Dummy param --- library/src/scala/IArray.scala | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 63c409528ca1..f96425fea036 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -326,48 +326,48 @@ object IArray: def +:(arr: IArray[U]): IArray[U] = genericArrayOps(arr).prepended(x) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapIArray[T](using DummyImplicit): Conversion[IArray[T], scala.collection.immutable.ArraySeq[T]] = - arr => scala.collection.immutable.ArraySeq.unsafeWrapArray(arr.asInstanceOf[Array[T]]) + implicit def genericWrapArray[T](arr: IArray[T]): scala.collection.immutable.ArraySeq[T] = + scala.collection.immutable.ArraySeq.unsafeWrapArray(arr.asInstanceOf[Array[T]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapAnyRefIArray[T <: AnyRef](using DummyImplicit): Conversion[IArray[T], scala.collection.immutable.ArraySeq[T]] = - arr => scala.collection.immutable.ArraySeq.ofRef(arr.asInstanceOf[Array[T]]) + implicit def wrapRefArray[T <: AnyRef](arr: IArray[T]): scala.collection.immutable.ArraySeq[T] = + scala.collection.immutable.ArraySeq.ofRef(arr.asInstanceOf[Array[T]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapIntIArray(using DummyImplicit): Conversion[IArray[Int], scala.collection.immutable.ArraySeq[Int]] = - arr => scala.collection.immutable.ArraySeq.ofInt(arr.asInstanceOf[Array[Int]]) + implicit def wrapIntArray(arr: IArray[Int]): scala.collection.immutable.ArraySeq[Int] = + scala.collection.immutable.ArraySeq.ofInt(arr.asInstanceOf[Array[Int]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapDoubleIArray(using DummyImplicit): Conversion[IArray[Double], scala.collection.immutable.ArraySeq[Double]] = - arr => scala.collection.immutable.ArraySeq.ofDouble(arr.asInstanceOf[Array[Double]]) + implicit def wrapDoubleIArray(arr: IArray[Double]): collection.immutable.ArraySeq[Double] = + scala.collection.immutable.ArraySeq.ofDouble(arr.asInstanceOf[Array[Double]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapLongIArray(using DummyImplicit): Conversion[IArray[Long], scala.collection.immutable.ArraySeq[Long]] = - arr => scala.collection.immutable.ArraySeq.ofLong(arr.asInstanceOf[Array[Long]]) + implicit def wrapLongIArray(arr: IArray[Long]): collection.immutable.ArraySeq[Long] = + scala.collection.immutable.ArraySeq.ofLong(arr.asInstanceOf[Array[Long]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapFloatIArray(using DummyImplicit): Conversion[IArray[Float], scala.collection.immutable.ArraySeq[Float]] = - arr => scala.collection.immutable.ArraySeq.ofFloat(arr.asInstanceOf[Array[Float]]) + implicit def wrapFloatIArray(arr: IArray[Float]): collection.immutable.ArraySeq[Float] = + scala.collection.immutable.ArraySeq.ofFloat(arr.asInstanceOf[Array[Float]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapCharIArray(using DummyImplicit): Conversion[IArray[Char], scala.collection.immutable.ArraySeq[Char]] = - arr => scala.collection.immutable.ArraySeq.ofChar(arr.asInstanceOf[Array[Char]]) + implicit def wrapCharIArray(arr: IArray[Char]): collection.immutable.ArraySeq[Char] = + scala.collection.immutable.ArraySeq.ofChar(arr.asInstanceOf[Array[Char]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapByteIArray(using DummyImplicit): Conversion[IArray[Byte], scala.collection.immutable.ArraySeq[Byte]] = - arr => scala.collection.immutable.ArraySeq.ofByte(arr.asInstanceOf[Array[Byte]]) + implicit def wrapByteIArray(arr: IArray[Byte]): collection.immutable.ArraySeq[Byte] = + scala.collection.immutable.ArraySeq.ofByte(arr.asInstanceOf[Array[Byte]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapShortIArray(using DummyImplicit): Conversion[IArray[Short], scala.collection.immutable.ArraySeq[Short]] = - arr => scala.collection.immutable.ArraySeq.ofShort(arr.asInstanceOf[Array[Short]]) + implicit def wrapShortIArray(arr: IArray[Short]): collection.immutable.ArraySeq[Short] = + scala.collection.immutable.ArraySeq.ofShort(arr.asInstanceOf[Array[Short]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapBooleanIArray(using DummyImplicit): Conversion[IArray[Boolean], scala.collection.immutable.ArraySeq[Boolean]] = - arr => scala.collection.immutable.ArraySeq.ofBoolean(arr.asInstanceOf[Array[Boolean]]) + implicit def wrapBooleanIArray(arr: IArray[Boolean]): collection.immutable.ArraySeq[Boolean] = + scala.collection.immutable.ArraySeq.ofBoolean(arr.asInstanceOf[Array[Boolean]]) /** Conversion from IArray to immutable.ArraySeq */ - given genericWrapUnitIArray(using DummyImplicit): Conversion[IArray[Unit], scala.collection.immutable.ArraySeq[Unit]] = - arr => scala.collection.immutable.ArraySeq.ofUnit(arr.asInstanceOf[Array[Unit]]) + implicit def wrapUnitIArray(arr: IArray[Unit]): collection.immutable.ArraySeq[Unit] = + scala.collection.immutable.ArraySeq.ofUnit(arr.asInstanceOf[Array[Unit]]) /** Convert an array into an immutable array without copying, the original array * must _not_ be mutated after this or the guaranteed immutablity of IArray will From 90393417980f0b59c21aae32afebe2b61c3a1c76 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Feb 2021 15:03:03 +0100 Subject: [PATCH 07/10] Align converions with Array conversions in Predef --- library/src/scala/IArray.scala | 49 +++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index f96425fea036..5cb0805b594a 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -326,48 +326,53 @@ object IArray: def +:(arr: IArray[U]): IArray[U] = genericArrayOps(arr).prepended(x) /** Conversion from IArray to immutable.ArraySeq */ - implicit def genericWrapArray[T](arr: IArray[T]): scala.collection.immutable.ArraySeq[T] = - scala.collection.immutable.ArraySeq.unsafeWrapArray(arr.asInstanceOf[Array[T]]) + implicit def genericWrapArray[T](arr: IArray[T]): immutable.ArraySeq[T] = + if arr eq null then null else immutable.ArraySeq.unsafeWrapArray(arr) /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapRefArray[T <: AnyRef](arr: IArray[T]): scala.collection.immutable.ArraySeq[T] = - scala.collection.immutable.ArraySeq.ofRef(arr.asInstanceOf[Array[T]]) + implicit def wrapRefArray[T <: AnyRef](arr: IArray[T]): immutable.ArraySeq.ofRef[T] = + // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] + // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 + // unique ones by way of this implicit, let's share one. + if (arr eq null) null + else if (arr.length == 0) immutable.ArraySeq.empty[AnyRef].asInstanceOf[immutable.ArraySeq.ofRef[T]] + else immutable.ArraySeq.ofRef(arr.asInstanceOf[Array[T]]) /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapIntArray(arr: IArray[Int]): scala.collection.immutable.ArraySeq[Int] = - scala.collection.immutable.ArraySeq.ofInt(arr.asInstanceOf[Array[Int]]) + implicit def wrapIntArray(arr: IArray[Int]): immutable.ArraySeq.ofInt = + if (arr ne null) new immutable.ArraySeq.ofInt(arr.asInstanceOf[Array[Int]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapDoubleIArray(arr: IArray[Double]): collection.immutable.ArraySeq[Double] = - scala.collection.immutable.ArraySeq.ofDouble(arr.asInstanceOf[Array[Double]]) + implicit def wrapDoubleIArray(arr: IArray[Double]): immutable.ArraySeq.ofDouble = + if (arr ne null) new immutable.ArraySeq.ofDouble(arr.asInstanceOf[Array[Double]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapLongIArray(arr: IArray[Long]): collection.immutable.ArraySeq[Long] = - scala.collection.immutable.ArraySeq.ofLong(arr.asInstanceOf[Array[Long]]) + implicit def wrapLongIArray(arr: IArray[Long]): immutable.ArraySeq.ofLong = + if (arr ne null) new immutable.ArraySeq.ofLong(arr.asInstanceOf[Array[Long]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapFloatIArray(arr: IArray[Float]): collection.immutable.ArraySeq[Float] = - scala.collection.immutable.ArraySeq.ofFloat(arr.asInstanceOf[Array[Float]]) + implicit def wrapFloatIArray(arr: IArray[Float]): immutable.ArraySeq.ofFloat = + if (arr ne null) new immutable.ArraySeq.ofFloat(arr.asInstanceOf[Array[Float]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapCharIArray(arr: IArray[Char]): collection.immutable.ArraySeq[Char] = - scala.collection.immutable.ArraySeq.ofChar(arr.asInstanceOf[Array[Char]]) + implicit def wrapCharIArray(arr: IArray[Char]): immutable.ArraySeq.ofChar = + if (arr ne null) new immutable.ArraySeq.ofChar(arr.asInstanceOf[Array[Char]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapByteIArray(arr: IArray[Byte]): collection.immutable.ArraySeq[Byte] = - scala.collection.immutable.ArraySeq.ofByte(arr.asInstanceOf[Array[Byte]]) + implicit def wrapByteIArray(arr: IArray[Byte]): immutable.ArraySeq.ofByte = + if (arr ne null) new immutable.ArraySeq.ofByte(arr.asInstanceOf[Array[Byte]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapShortIArray(arr: IArray[Short]): collection.immutable.ArraySeq[Short] = - scala.collection.immutable.ArraySeq.ofShort(arr.asInstanceOf[Array[Short]]) + implicit def wrapShortIArray(arr: IArray[Short]): immutable.ArraySeq.ofShort = + if (arr ne null) new immutable.ArraySeq.ofShort(arr.asInstanceOf[Array[Short]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapBooleanIArray(arr: IArray[Boolean]): collection.immutable.ArraySeq[Boolean] = - scala.collection.immutable.ArraySeq.ofBoolean(arr.asInstanceOf[Array[Boolean]]) + implicit def wrapBooleanIArray(arr: IArray[Boolean]): immutable.ArraySeq.ofBoolean = + if (arr ne null) new immutable.ArraySeq.ofBoolean(arr.asInstanceOf[Array[Boolean]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapUnitIArray(arr: IArray[Unit]): collection.immutable.ArraySeq[Unit] = - scala.collection.immutable.ArraySeq.ofUnit(arr.asInstanceOf[Array[Unit]]) + implicit def wrapUnitIArray(arr: IArray[Unit]): immutable.ArraySeq.ofUnit = + if (arr ne null) new immutable.ArraySeq.ofUnit(arr.asInstanceOf[Array[Unit]]) else null /** Convert an array into an immutable array without copying, the original array * must _not_ be mutated after this or the guaranteed immutablity of IArray will From 46c0540904b814ba0ac100f1a2a75f7b74030a2f Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Feb 2021 15:25:41 +0100 Subject: [PATCH 08/10] Cleanup imports --- library/src/scala/IArray.scala | 55 +++++++++++++++++----------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 5cb0805b594a..ef29d2f346ad 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -1,7 +1,8 @@ package scala import reflect.ClassTag -import scala.collection._ +import scala.collection.{LazyZip2, SeqView, Searching, Stepper, StepperShape} +import scala.collection.immutable.ArraySeq import scala.collection.mutable.IArrayBuilder opaque type IArray[+T] = Array[_ <: T] @@ -276,8 +277,8 @@ object IArray: def startsWith[U >: T](that: IterableOnce[U], offset: Int): Boolean = genericArrayOps(arr).startsWith(that, offset) def endsWith[U >: T](that: IArray[U]): Boolean = genericArrayOps(arr).endsWith(that) def endsWith[U >: T](that: Iterable[U]): Boolean = genericArrayOps(arr).endsWith(that) - def groupBy[K](f: T => K): immutable.Map[K, IArray[T]] = genericArrayOps(arr).groupBy(f) - def groupMap[K, U: ClassTag](key: T => K)(f: T => U): immutable.Map[K, IArray[U]] = genericArrayOps(arr).groupMap(key)(f) + def groupBy[K](f: T => K): Map[K, IArray[T]] = genericArrayOps(arr).groupBy(f) + def groupMap[K, U: ClassTag](key: T => K)(f: T => U): Map[K, IArray[U]] = genericArrayOps(arr).groupMap(key)(f) def grouped(size: Int): Iterator[IArray[T]] = genericArrayOps(arr).grouped(size) def inits: Iterator[IArray[T]] = genericArrayOps(arr).inits def intersect[U >: T](that: IArray[U]): IArray[T] = genericArrayOps(arr).intersect(that) @@ -326,53 +327,53 @@ object IArray: def +:(arr: IArray[U]): IArray[U] = genericArrayOps(arr).prepended(x) /** Conversion from IArray to immutable.ArraySeq */ - implicit def genericWrapArray[T](arr: IArray[T]): immutable.ArraySeq[T] = - if arr eq null then null else immutable.ArraySeq.unsafeWrapArray(arr) + implicit def genericWrapArray[T](arr: IArray[T]): ArraySeq[T] = + if arr eq null then null else ArraySeq.unsafeWrapArray(arr) /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapRefArray[T <: AnyRef](arr: IArray[T]): immutable.ArraySeq.ofRef[T] = + implicit def wrapRefArray[T <: AnyRef](arr: IArray[T]): ArraySeq.ofRef[T] = // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 // unique ones by way of this implicit, let's share one. if (arr eq null) null - else if (arr.length == 0) immutable.ArraySeq.empty[AnyRef].asInstanceOf[immutable.ArraySeq.ofRef[T]] - else immutable.ArraySeq.ofRef(arr.asInstanceOf[Array[T]]) + else if (arr.length == 0) ArraySeq.empty[AnyRef].asInstanceOf[ArraySeq.ofRef[T]] + else ArraySeq.ofRef(arr.asInstanceOf[Array[T]]) /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapIntArray(arr: IArray[Int]): immutable.ArraySeq.ofInt = - if (arr ne null) new immutable.ArraySeq.ofInt(arr.asInstanceOf[Array[Int]]) else null + implicit def wrapIntArray(arr: IArray[Int]): ArraySeq.ofInt = + if (arr ne null) new ArraySeq.ofInt(arr.asInstanceOf[Array[Int]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapDoubleIArray(arr: IArray[Double]): immutable.ArraySeq.ofDouble = - if (arr ne null) new immutable.ArraySeq.ofDouble(arr.asInstanceOf[Array[Double]]) else null + implicit def wrapDoubleIArray(arr: IArray[Double]): ArraySeq.ofDouble = + if (arr ne null) new ArraySeq.ofDouble(arr.asInstanceOf[Array[Double]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapLongIArray(arr: IArray[Long]): immutable.ArraySeq.ofLong = - if (arr ne null) new immutable.ArraySeq.ofLong(arr.asInstanceOf[Array[Long]]) else null + implicit def wrapLongIArray(arr: IArray[Long]): ArraySeq.ofLong = + if (arr ne null) new ArraySeq.ofLong(arr.asInstanceOf[Array[Long]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapFloatIArray(arr: IArray[Float]): immutable.ArraySeq.ofFloat = - if (arr ne null) new immutable.ArraySeq.ofFloat(arr.asInstanceOf[Array[Float]]) else null + implicit def wrapFloatIArray(arr: IArray[Float]): ArraySeq.ofFloat = + if (arr ne null) new ArraySeq.ofFloat(arr.asInstanceOf[Array[Float]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapCharIArray(arr: IArray[Char]): immutable.ArraySeq.ofChar = - if (arr ne null) new immutable.ArraySeq.ofChar(arr.asInstanceOf[Array[Char]]) else null + implicit def wrapCharIArray(arr: IArray[Char]): ArraySeq.ofChar = + if (arr ne null) new ArraySeq.ofChar(arr.asInstanceOf[Array[Char]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapByteIArray(arr: IArray[Byte]): immutable.ArraySeq.ofByte = - if (arr ne null) new immutable.ArraySeq.ofByte(arr.asInstanceOf[Array[Byte]]) else null + implicit def wrapByteIArray(arr: IArray[Byte]): ArraySeq.ofByte = + if (arr ne null) new ArraySeq.ofByte(arr.asInstanceOf[Array[Byte]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapShortIArray(arr: IArray[Short]): immutable.ArraySeq.ofShort = - if (arr ne null) new immutable.ArraySeq.ofShort(arr.asInstanceOf[Array[Short]]) else null + implicit def wrapShortIArray(arr: IArray[Short]): ArraySeq.ofShort = + if (arr ne null) new ArraySeq.ofShort(arr.asInstanceOf[Array[Short]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapBooleanIArray(arr: IArray[Boolean]): immutable.ArraySeq.ofBoolean = - if (arr ne null) new immutable.ArraySeq.ofBoolean(arr.asInstanceOf[Array[Boolean]]) else null + implicit def wrapBooleanIArray(arr: IArray[Boolean]): ArraySeq.ofBoolean = + if (arr ne null) new ArraySeq.ofBoolean(arr.asInstanceOf[Array[Boolean]]) else null /** Conversion from IArray to immutable.ArraySeq */ - implicit def wrapUnitIArray(arr: IArray[Unit]): immutable.ArraySeq.ofUnit = - if (arr ne null) new immutable.ArraySeq.ofUnit(arr.asInstanceOf[Array[Unit]]) else null + implicit def wrapUnitIArray(arr: IArray[Unit]): ArraySeq.ofUnit = + if (arr ne null) new ArraySeq.ofUnit(arr.asInstanceOf[Array[Unit]]) else null /** Convert an array into an immutable array without copying, the original array * must _not_ be mutated after this or the guaranteed immutablity of IArray will @@ -451,7 +452,7 @@ object IArray: // `Array.concat` should arguably take in a `Seq[Array[_ <: T]]`, // but since it currently takes a `Seq[Array[T]]` we have to perform a cast, // knowing tacitly that `concat` is not going to do the wrong thing. - Array.concat[T](xss.asInstanceOf[immutable.Seq[Array[T]]]: _*) + Array.concat[T](xss.asInstanceOf[Seq[Array[T]]]: _*) /** Returns an immutable array that contains the results of some element computation a number * of times. Each element is determined by a separate computation. From 0b9c0179f5a09fb58cfd0434dbd232044a434c2f Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Feb 2021 16:08:02 +0100 Subject: [PATCH 09/10] Make add all also recive Arrays These call use `java.lang.System.arraycopy` to add the elements --- library/src/scala/collection/mutable/IArrayBuilder.scala | 4 ++-- tests/run/IArrayOps.scala | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/library/src/scala/collection/mutable/IArrayBuilder.scala b/library/src/scala/collection/mutable/IArrayBuilder.scala index 254c735e2ecc..7383fa1de7c0 100644 --- a/library/src/scala/collection/mutable/IArrayBuilder.scala +++ b/library/src/scala/collection/mutable/IArrayBuilder.scala @@ -17,12 +17,12 @@ sealed abstract class IArrayBuilder[T] def clear(): Unit = arrayBuilder.clear() /** Add all elements of an array */ - def addAll(xs: IArray[T]): this.type = + def addAll(xs: IArray[T] | Array[_ <: T]): this.type = arrayBuilder.addAll(xs.asInstanceOf[Array[T]]) this /** Add a slice of an array */ - def addAll(xs: IArray[T], offset: Int, length: Int): this.type = + def addAll(xs: IArray[T] | Array[_ <: T], offset: Int, length: Int): this.type = arrayBuilder.addAll(xs.asInstanceOf[Array[T]], offset, length) this diff --git a/tests/run/IArrayOps.scala b/tests/run/IArrayOps.scala index 9a2f4672daae..81a6e3c2a11b 100644 --- a/tests/run/IArrayOps.scala +++ b/tests/run/IArrayOps.scala @@ -1,11 +1,6 @@ @main def Test: Unit = val iarr1 = IArray(1, 2, 3) val iarr2 = IArray(5, 4, 5, 6) - // val iarr3 = IArray( - // IArray(1, 2, 3), - // IArray(4, 5, 6), - // IArray(7, 8, 9) - // ) println(iarr1.toSeq) println(iarr1.contains(1)) From c2659570bb8c22d8dec04fccf016a822f9bd7d11 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Feb 2021 17:20:03 +0100 Subject: [PATCH 10/10] Remove IArrayBuilder --- library/src/scala/IArray.scala | 10 +- .../collection/mutable/IArrayBuilder.scala | 192 ------------------ 2 files changed, 5 insertions(+), 197 deletions(-) delete mode 100644 library/src/scala/collection/mutable/IArrayBuilder.scala diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index ef29d2f346ad..0fcdfcec669c 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -3,7 +3,7 @@ import reflect.ClassTag import scala.collection.{LazyZip2, SeqView, Searching, Stepper, StepperShape} import scala.collection.immutable.ArraySeq -import scala.collection.mutable.IArrayBuilder +import scala.collection.mutable.{ArrayBuilder, Builder} opaque type IArray[+T] = Array[_ <: T] @@ -440,8 +440,8 @@ object IArray: def from[A : ClassTag](it: IterableOnce[A]): Array[A] = Array.from(it) - def newBuilder[T](using t: ClassTag[T]): IArrayBuilder[T] = - IArrayBuilder.make[T] + def newBuilder[T](using t: ClassTag[T]): Builder[T, IArray[T]] = + ArrayBuilder.make[T].mapResult(IArray.unsafeFromArray) /** Concatenates all arrays into a single immutable array. * @@ -635,7 +635,7 @@ object IArray: * `f` to each element of this array and collecting the results. */ def map[U: ClassTag](f: T => U): IArray[U] = { - val b = IArrayBuilder.make[U] + val b = IArray.newBuilder[U] var i = 0 while (i < xs.length) { val x = xs(i) @@ -654,7 +654,7 @@ object IArray: * `f` to each element of this array and concatenating the results. */ def flatMap[U: ClassTag](f: T => IterableOnce[U]): IArray[U] = { - val b = IArrayBuilder.make[U] + val b = IArray.newBuilder[U] var i = 0 while(i < xs.length) { val x = xs(i) diff --git a/library/src/scala/collection/mutable/IArrayBuilder.scala b/library/src/scala/collection/mutable/IArrayBuilder.scala deleted file mode 100644 index 7383fa1de7c0..000000000000 --- a/library/src/scala/collection/mutable/IArrayBuilder.scala +++ /dev/null @@ -1,192 +0,0 @@ -package scala.collection.mutable - -import scala.reflect.ClassTag - -/** A builder class for immutable arrays. - * - * @tparam T the type of the elements for the builder. - */ -@SerialVersionUID(3L) -sealed abstract class IArrayBuilder[T] - extends ReusableBuilder[T, IArray[T]] - with Serializable { - - protected[this] val arrayBuilder: ArrayBuilder[T] - - override final def sizeHint(size: Int): Unit = arrayBuilder.sizeHint(size) - def clear(): Unit = arrayBuilder.clear() - - /** Add all elements of an array */ - def addAll(xs: IArray[T] | Array[_ <: T]): this.type = - arrayBuilder.addAll(xs.asInstanceOf[Array[T]]) - this - - /** Add a slice of an array */ - def addAll(xs: IArray[T] | Array[_ <: T], offset: Int, length: Int): this.type = - arrayBuilder.addAll(xs.asInstanceOf[Array[T]], offset, length) - this - - override def addAll(xs: IterableOnce[T]): this.type = - arrayBuilder.addAll(xs) - this -} - -/** A companion object for array builders. */ -object IArrayBuilder { - - /** Creates a new arraybuilder of type `T`. - * - * @tparam T type of the elements for the array builder, with a `ClassTag` context bound. - * @return a new empty array builder. - */ - @inline def make[T: ClassTag]: IArrayBuilder[T] = { - val tag = implicitly[ClassTag[T]] - tag.runtimeClass match { - case java.lang.Byte.TYPE => new IArrayBuilder.ofByte().asInstanceOf[IArrayBuilder[T]] - case java.lang.Short.TYPE => new IArrayBuilder.ofShort().asInstanceOf[IArrayBuilder[T]] - case java.lang.Character.TYPE => new IArrayBuilder.ofChar().asInstanceOf[IArrayBuilder[T]] - case java.lang.Integer.TYPE => new IArrayBuilder.ofInt().asInstanceOf[IArrayBuilder[T]] - case java.lang.Long.TYPE => new IArrayBuilder.ofLong().asInstanceOf[IArrayBuilder[T]] - case java.lang.Float.TYPE => new IArrayBuilder.ofFloat().asInstanceOf[IArrayBuilder[T]] - case java.lang.Double.TYPE => new IArrayBuilder.ofDouble().asInstanceOf[IArrayBuilder[T]] - case java.lang.Boolean.TYPE => new IArrayBuilder.ofBoolean().asInstanceOf[IArrayBuilder[T]] - case java.lang.Void.TYPE => new IArrayBuilder.ofUnit().asInstanceOf[IArrayBuilder[T]] - case _ => new IArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[IArrayBuilder[T]] - } - } - - /** A class for array builders for arrays of reference types. - * - * This builder can be reused. - * - * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassTag` context bound. - */ - @SerialVersionUID(3L) - final class ofRef[T <: AnyRef](implicit ct: ClassTag[T]) extends IArrayBuilder[T] { - protected[this] val arrayBuilder: ArrayBuilder[T] = new ArrayBuilder.ofRef - def addOne(elem: T): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[T] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofRef[_] => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofRef" - } - - /** A class for array builders for arrays of `byte`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofByte extends IArrayBuilder[Byte] { - protected[this] val arrayBuilder: ArrayBuilder[Byte] = new ArrayBuilder.ofByte - def addOne(elem: Byte): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Byte] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofByte => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofByte" - } - - /** A class for array builders for arrays of `short`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofShort extends IArrayBuilder[Short] { - protected[this] val arrayBuilder: ArrayBuilder[Short] = new ArrayBuilder.ofShort - def addOne(elem: Short): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Short] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofShort => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofShort" - } - - /** A class for array builders for arrays of `char`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofChar extends IArrayBuilder[Char] { - protected[this] val arrayBuilder: ArrayBuilder[Char] = new ArrayBuilder.ofChar - def addOne(elem: Char): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Char] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofChar => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofChar" - } - - /** A class for array builders for arrays of `int`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofInt extends IArrayBuilder[Int] { - protected[this] val arrayBuilder: ArrayBuilder[Int] = new ArrayBuilder.ofInt - def addOne(elem: Int): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Int] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofInt => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofInt" - } - - /** A class for array builders for arrays of `long`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofLong extends IArrayBuilder[Long] { - protected[this] val arrayBuilder: ArrayBuilder[Long] = new ArrayBuilder.ofLong - def addOne(elem: Long): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Long] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofLong => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofLong" - } - - /** A class for array builders for arrays of `float`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofFloat extends IArrayBuilder[Float] { - protected[this] val arrayBuilder: ArrayBuilder[Float] = new ArrayBuilder.ofFloat - def addOne(elem: Float): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Float] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofFloat => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofFloat" - } - - /** A class for array builders for arrays of `double`s. It can be reused. */ - @SerialVersionUID(3L) - final class ofDouble extends IArrayBuilder[Double] { - protected[this] val arrayBuilder: ArrayBuilder[Double] = new ArrayBuilder.ofDouble - def addOne(elem: Double): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Double] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofDouble => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofDouble" - } - - /** A class for array builders for arrays of `boolean`s. It can be reused. */ - @SerialVersionUID(3L) - class ofBoolean extends IArrayBuilder[Boolean] { - protected[this] val arrayBuilder: ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean - def addOne(elem: Boolean): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Boolean] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofBoolean => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofBoolean" - } - - /** A class for array builders for arrays of `Unit` type. It can be reused. */ - @SerialVersionUID(3L) - final class ofUnit extends IArrayBuilder[Unit] { - protected[this] val arrayBuilder: ArrayBuilder[Unit] = new ArrayBuilder.ofUnit - def addOne(elem: Unit): this.type = { arrayBuilder.addOne(elem); this } - def result(): IArray[Unit] = IArray.unsafeFromArray(arrayBuilder.result()) - override def equals(other: Any): Boolean = other match { - case x: ofUnit => this.arrayBuilder == x.arrayBuilder - case _ => false - } - override def toString = "IArrayBuilder.ofUnit" - } -}