diff --git a/library/src-bootstrapped/scala/IArray.scala b/library/src-bootstrapped/scala/IArray.scala index 85b7188c49a0..7a2d2f68c39b 100644 --- a/library/src-bootstrapped/scala/IArray.scala +++ b/library/src-bootstrapped/scala/IArray.scala @@ -38,6 +38,223 @@ object opaques def (arr: IArray[Double]) length: Int = arr.asInstanceOf[Array[Double]].length def (arr: IArray[Object]) length: Int = arr.asInstanceOf[Array[Object]].length def [T](arr: IArray[T]) length: Int = arr.asInstanceOf[Array[T]].length + + /** Returns this array concatenated with the given array. */ + def [T, U >: T: ClassTag](arr: IArray[T]) ++(that: IArray[U]): IArray[U] = + (genericArrayOps(arr) ++ that.asInstanceOf[Array[U]]).asInstanceOf[IArray[U]] + + /** Tests whether this array contains a given value as an element. */ + def [T](arr: IArray[T]) contains(elem: T): Boolean = + genericArrayOps(arr.asInstanceOf[Array[T]]).contains(elem) + + /** Counts the number of elements in this array which satisfy a predicate */ + def [T](arr: IArray[T]) count(p: T => Boolean): Int = + genericArrayOps(arr).count(p) + + /** The rest of the array without its `n` first elements. */ + def [T](arr: IArray[T]) drop(n: Int): IArray[T] = + genericArrayOps(arr).drop(n).asInstanceOf[IArray[T]] + + /** The rest of the array without its `n` last elements. */ + def [T](arr: IArray[T]) dropRight(n: Int): IArray[T] = + genericArrayOps(arr).dropRight(n).asInstanceOf[IArray[T]] + + /** Drops longest prefix of elements that satisfy a predicate. */ + def [T](arr: IArray[T]) dropWhile(p: T => Boolean): IArray[T] = + genericArrayOps(arr).dropWhile(p).asInstanceOf[IArray[T]] + + /** Tests whether a predicate holds for at least one element of this array. */ + def [T](arr: IArray[T]) exists(p: T => Boolean): IArray[T] = + genericArrayOps(arr).exists(p).asInstanceOf[IArray[T]] + + /** Selects all elements of this array which satisfy a predicate. */ + def [T](arr: IArray[T]) filter(p: T => Boolean): IArray[T] = + genericArrayOps(arr).filter(p).asInstanceOf[IArray[T]] + + /** Selects all elements of this array which do not satisfy a predicate. */ + def [T](arr: IArray[T]) filterNot(p: T => Boolean): IArray[T] = + genericArrayOps(arr).filterNot(p).asInstanceOf[IArray[T]] + + /** Finds the first element of the array satisfying a predicate, if any. */ + def [T](arr: IArray[T]) find(p: T => Boolean): Option[T] = + genericArrayOps(arr).find(p) + + /** Builds a new array by applying a function to all elements of this array + * and using the elements of the resulting collections. */ + def [T, U: ClassTag](arr: IArray[T]) flatMap(f: T => IterableOnce[U]): IArray[U] = + genericArrayOps(arr).flatMap(f).asInstanceOf[IArray[U]] + + /** Flattens a two-dimensional array by concatenating all its rows + * into a single array. */ + def [T, U: ClassTag](arr: IArray[T]) flatten(given T => Iterable[U]): IArray[U] = + genericArrayOps(arr).flatten.asInstanceOf[IArray[U]] + + /** Folds the elements of this array using the specified associative binary operator. */ + def [T, U >: T: ClassTag](arr: IArray[T]) fold(z: U)(op: (U, U) => U): U = + genericArrayOps(arr).fold(z)(op) + + /** Applies a binary operator to a start value and all elements of this array, + * going left to right. */ + def [T, U: ClassTag](arr: IArray[T]) foldLeft(z: U)(op: (U, T) => U): U = + genericArrayOps(arr).foldLeft(z)(op) + + /** Applies a binary operator to all elements of this array and a start value, + * going right to left. */ + def [T, U: ClassTag](arr: IArray[T]) foldRight(z: U)(op: (T, U) => U): U = + genericArrayOps(arr).foldRight(z)(op) + + /** Tests whether a predicate holds for all elements of this array. */ + def [T](arr: IArray[T]) forall(p: T => Boolean): Boolean = + genericArrayOps(arr).forall(p) + + /** Apply `f` to each element for its side effects. */ + def [T, U](arr: IArray[T]) foreach(f: T => U): Unit = + genericArrayOps(arr).foreach(f) + + /** Selects the first element of this array. */ + def [T](arr: IArray[T]) head: T = + genericArrayOps(arr).head + + /** Optionally selects the first element. */ + def [T](arr: IArray[T]) headOption: Option[T] = + genericArrayOps(arr).headOption + + /** Finds index of first occurrence of some value in this array after or at some start index. */ + def [T](arr: IArray[T]) indexOf(elem: T, from: Int = 0): Int = + genericArrayOps(arr.asInstanceOf[Array[T]]).indexOf(elem, from) + + /** Finds index of the first element satisfying some predicate after or at some start index. */ + def [T](arr: IArray[T]) indexWhere(p: T => Boolean, from: Int = 0): Int = + genericArrayOps(arr).indexWhere(p, from) + + /** Produces the range of all indices of this sequence. */ + def [T](arr: IArray[T]) indices: Range = + genericArrayOps(arr).indices + + /** The initial part of the array without its last element. */ + def [T](arr: IArray[T]) init: IArray[T] = + genericArrayOps(arr).init.asInstanceOf[IArray[T]] + + /** Tests whether the array is empty. */ + def [T](arr: IArray[T]) isEmpty: Boolean = + genericArrayOps(arr).isEmpty + + /** An iterator yielding the elemenst of this array. */ + def [T](arr: IArray[T]) iterator: Iterator[T] = + genericArrayOps(arr).iterator + + /** Selects the last element. */ + def [T](arr: IArray[T]) last: T = + genericArrayOps(arr).last + + /** Optionally selects the last element. */ + def [T](arr: IArray[T]) lastOption: Option[T] = + genericArrayOps(arr).lastOption + + /** Finds index of last occurrence of some value in this array before or at a given end index. */ + def [T](arr: IArray[T]) lastIndexOf(elem: T, end: Int = arr.length - 1): Int = + genericArrayOps(arr.asInstanceOf[Array[T]]).lastIndexOf(elem, end) + + /** Finds index of last element satisfying some predicate before or at given end index. */ + def [T](arr: IArray[T]) lastIndexWhere(p: T => Boolean, end: Int = arr.length - 1): Int = + genericArrayOps(arr).lastIndexWhere(p, end) + + /** Builds a new array by applying a function to all elements of this array. */ + def [T, U: ClassTag](arr: IArray[T]) map(f: T => U): IArray[U] = + genericArrayOps(arr).map(f).asInstanceOf[IArray[U]] + + /** Tests whether the array is not empty. */ + def [T](arr: IArray[T]) nonEmpty: Boolean = + genericArrayOps(arr).nonEmpty + + /** A pair of, first, all elements that satisfy predicate `p` and, second, all elements that do not. */ + def [T](arr: IArray[T]) partition(p: T => Boolean): (IArray[T], IArray[T]) = + genericArrayOps(arr).partition(p) match { + case (x, y) => (x.asInstanceOf[IArray[T]], y.asInstanceOf[IArray[T]]) + } + + /** Returns a new array with the elements in reversed order. */ + def [T](arr: IArray[T]) reverse: IArray[T] = + genericArrayOps(arr).reverse.asInstanceOf[IArray[T]] + + /** Computes a prefix scan of the elements of the array. */ + def [T, U >: T: ClassTag](arr: IArray[T]) scan(z: U)(op: (U, U) => U): IArray[U] = + genericArrayOps(arr).scan(z)(op).asInstanceOf[IArray[U]] + + /** Produces an array containing cumulative results of applying the binary + * operator going left to right. */ + def [T, U: ClassTag](arr: IArray[T]) scanLeft(z: U)(op: (U, T) => U): IArray[U] = + genericArrayOps(arr).scanLeft(z)(op).asInstanceOf[IArray[U]] + + /** Produces an array containing cumulative results of applying the binary + * operator going right to left. */ + def [T, U: ClassTag](arr: IArray[T]) scanRight(z: U)(op: (T, U) => U): IArray[U] = + genericArrayOps(arr).scanRight(z)(op).asInstanceOf[IArray[U]] + + /** The size of this array. */ + def [T](arr: IArray[T]) size: Int = + arr.length + + /** Selects the interval of elements between the given indices. */ + def [T](arr: IArray[T]) slice(from: Int, until: Int): IArray[T] = + genericArrayOps(arr).slice(from, until).asInstanceOf[IArray[T]] + + /** Sorts this array according to the Ordering which results from transforming + * an implicitly given Ordering with a transformation function. */ + def [T, U: ClassTag](arr: IArray[T]) sortBy(f: T => U)(given math.Ordering[U]): IArray[T] = + genericArrayOps(arr).sortBy(f).asInstanceOf[IArray[T]] + + /** Sorts this array according to a comparison function. */ + def [T](arr: IArray[T]) sortWith(f: (T, T) => Boolean): IArray[T] = + genericArrayOps(arr).sortWith(f).asInstanceOf[IArray[T]] + + /** Sorts this array according to an Ordering. */ + def [T](arr: IArray[T]) sorted(given math.Ordering[T]): IArray[T] = + genericArrayOps(arr).sorted.asInstanceOf[IArray[T]] + + /** Splits this array into a prefix/suffix pair according to a predicate. */ + def [T](arr: IArray[T]) span(p: T => Boolean): (IArray[T], IArray[T]) = + genericArrayOps(arr).span(p) match { + case (x, y) => (x.asInstanceOf[IArray[T]], y.asInstanceOf[IArray[T]]) + } + + /** Splits this array into two at a given position. */ + def [T](arr: IArray[T]) splitAt(n: Int): (IArray[T], IArray[T]) = + genericArrayOps(arr).splitAt(n) match { + case (x, y) => (x.asInstanceOf[IArray[T]], y.asInstanceOf[IArray[T]]) + } + + /** Tests whether this array starts with the given array. */ + def [T, U >: T: ClassTag](arr: IArray[T]) startsWith(that: IArray[U], offset: Int = 0): Boolean = + genericArrayOps(arr).startsWith(that.asInstanceOf[Array[U]]) + + /** The rest of the array without its first element. */ + def [T](arr: IArray[T]) tail: IArray[T] = + genericArrayOps(arr).tail.asInstanceOf[IArray[T]] + + /** An array containing the first `n` elements of this array. */ + def [T](arr: IArray[T]) take(n: Int): IArray[T] = + genericArrayOps(arr).take(n).asInstanceOf[IArray[T]] + + /** An array containing the last `n` elements of this array. */ + def [T](arr: IArray[T]) takeRight(n: Int): IArray[T] = + genericArrayOps(arr).takeRight(n).asInstanceOf[IArray[T]] + + /** Takes longest prefix of elements that satisfy a predicate. */ + def [T](arr: IArray[T]) takeWhile(p: T => Boolean): IArray[T] = + genericArrayOps(arr).takeWhile(p).asInstanceOf[IArray[T]] + + /** Converts an array of pairs into an array of first elements and an array of second elements. */ + def [U: ClassTag, V: ClassTag](arr: IArray[(U, V)]) unzip: (IArray[U], IArray[V]) = + genericArrayOps(arr).unzip match { + case (x, y) => (x.asInstanceOf[IArray[U]], y.asInstanceOf[IArray[V]]) + } + + /** 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. */ + def [T, U: ClassTag](arr: IArray[T]) zip(that: IArray[U]): IArray[(T, U)] = + genericArrayOps(arr).zip(that).asInstanceOf[IArray[(T, U)]] end opaques type IArray[+T] = opaques.IArray[T] diff --git a/tests/run-bootstrapped/iarray-extmtds.check b/tests/run-bootstrapped/iarray-extmtds.check new file mode 100644 index 000000000000..584835a37ffc --- /dev/null +++ b/tests/run-bootstrapped/iarray-extmtds.check @@ -0,0 +1,63 @@ +IArray(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20) +true +5 +IArray(9,10) +IArray(1,2) +IArray(8,9,10) +true +IArray(2,4,6,8,10) +IArray(1,3,5,7,9) +Some(5) +IArray(1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10) +IArray(1,2,3,4) +55 +12345678910 +10987654321 +false +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +Some(1) +-1 +3 +0,1,2,3,4,5,6,7,8,9 +IArray(1,2,3,4,5,6,7,8,9) +false +1,2,3 +10 +Some(20) +6 +3 +IArray(11,12,13,14,15,16,17,18,19,20) +true +IArray(2,4,6,8,10) +IArray(1,3,5,7,9) +IArray(10,9,8,7,6,5,4,3,2,1) +IArray(0,1,3,6,10,15,21,28,36,45,55) +IArray(,1,12,123,1234,12345,123456,1234567,12345678,123456789,12345678910) +IArray(10987654321,1098765432,109876543,10987654,1098765,109876,10987,1098,109,10,) +10 +IArray(6,7) +IArray(10,9,8,7,6,5,4,3,2,1) +IArray(10,1,2,3,4,5,6,7,8,9) +IArray(1,2,3,4,5,6,7,8,9,10) +IArray(1,2,3,4) +IArray(5,6,7,8,9,10) +IArray(1,2,3,4,5,6,7) +IArray(8,9,10) +false +IArray(2,3,4,5,6,7,8,9,10) +IArray(1,2,3) +IArray(7,8,9,10) +IArray(1,2) +IArray(1,2,3) +IArray(1,2,3) +IArray((1,11),(2,12),(3,13),(4,14),(5,15),(6,16),(7,17),(8,18),(9,19),(10,20)) diff --git a/tests/run-bootstrapped/iarray-extmtds.scala b/tests/run-bootstrapped/iarray-extmtds.scala new file mode 100644 index 000000000000..ddc7610dd794 --- /dev/null +++ b/tests/run-bootstrapped/iarray-extmtds.scala @@ -0,0 +1,127 @@ + +object Test extends App { + def printIArray[T](arr: IArray[T]): Unit = + println(arr.asInstanceOf[Array[T]].mkString("IArray(", ",", ")")) + + // This is used to check the correct result, as well as checking that the IArray was not mutated in place + def assertDifferent[T, U](expr: IArray[T], sources: IArray[U]*): Unit = { + sources.foreach(source => + assert(expr.asInstanceOf[AnyRef] ne source.asInstanceOf[AnyRef], "IArray was mutated in place") + ) + + printIArray(expr) + } + + val arr1 = IArray[Int](1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + val arr2 = IArray[Int](11, 12, 13, 14, 15, 16, 17, 18, 19, 20) + + assertDifferent(arr1 ++ arr2, arr1, arr2) + + println(arr1.contains(7)) + + println(arr1.count(_ % 2 == 0)) + + assertDifferent(arr1.drop(8), arr1) + + assertDifferent(arr1.dropRight(8), arr1) + + assertDifferent(arr1.dropWhile(_ < 8), arr1) + + println(arr1.exists(_ % 6 == 0)) + + assertDifferent(arr1.filter(_ % 2 == 0), arr1) + + assertDifferent(arr1.filterNot(_ % 2 == 0), arr1) + + println(arr1.find(_ % 5 == 0)) + + assertDifferent(arr1.flatMap(x => List(x, x)), arr1) + + val twoDArr = IArray(List(1, 2), List(3, 4)) + assertDifferent(twoDArr.flatten[List[Int], Int], twoDArr) + + println(arr1.fold(0)(_ + _)) + + println(arr1.foldLeft("")((acc, x) => acc + x.toString)) + + println(arr1.foldRight("")((x, acc) => acc + x.toString)) + + println(arr1.forall(_ > 5)) + + arr1.foreach(x => println(x)) + + println(arr2.head) + + println(arr1.headOption) + + println(arr1.indexOf(5, 7)) + + println(arr1.indexWhere(_ > 3, 1)) + + println(arr2.indices.mkString(",")) + + assertDifferent(arr1.init, arr1) + + println(arr1.isEmpty) + + println(arr1.iterator.take(3).mkString(",")) + + println(arr1.last) + + println(arr2.lastOption) + + println(arr2.lastIndexOf(17)) + + println(arr1.lastIndexWhere(_ < 5)) + + assertDifferent(arr1.map(_ + 10), arr1) + + println(arr1.nonEmpty) + + val (even, odd) = arr1.partition(_ % 2 == 0) + assertDifferent(even, arr1) + assertDifferent(odd, arr1) + + assertDifferent(arr1.reverse, arr1) + + assertDifferent(arr1.scan(0)(_ + _), arr1) + + assertDifferent(arr1.scanLeft("")((acc, x) => acc + x.toString), arr1) + + assertDifferent(arr1.scanRight("")((x, acc) => acc + x.toString), arr1) + + println(arr2.size) + + assertDifferent(arr1.slice(5,7), arr1) + + assertDifferent(arr1.sortBy(- _), arr1) + + assertDifferent(arr1.sortWith((x, y) => x.toString.length > y.toString.length || x < y), arr1) + + assertDifferent(arr1.sorted, arr1) + + val (smaller, greater) = arr1.span(_ < 5) + assertDifferent(smaller, arr1) + assertDifferent(greater, arr1) + + val (first, last) = arr1.splitAt(7) + assertDifferent(first, arr1) + assertDifferent(last, arr1) + + println(arr1.startsWith(IArray(1,2,3,4,5,6,42))) + + assertDifferent(arr1.tail, arr1) + + assertDifferent(arr1.take(3), arr1) + + assertDifferent(arr1.takeRight(4), arr1) + + assertDifferent(arr1.takeWhile(_ < 3), arr1) + + val tupArr = IArray[(Int, String)]((1, "1"), (2, "2"), (3, "3")) + val (ints, strings) = tupArr.unzip + assertDifferent(ints, tupArr) + assertDifferent(strings, tupArr) + + assertDifferent(arr1.zip(arr2), arr1, arr2) +}