Skip to content

IArray extension methods #7795

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Dec 29, 2019
217 changes: 217 additions & 0 deletions library/src-bootstrapped/scala/IArray.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
63 changes: 63 additions & 0 deletions tests/run-bootstrapped/iarray-extmtds.check
Original file line number Diff line number Diff line change
@@ -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))
Loading