Skip to content

Commit d5dcb7b

Browse files
committed
Add missing IArray operations
1 parent 6f1252a commit d5dcb7b

File tree

3 files changed

+468
-19
lines changed

3 files changed

+468
-19
lines changed

library/src/scala/IArray.scala

Lines changed: 139 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package scala
22
import reflect.ClassTag
33

4-
import scala.collection.immutable
4+
import scala.collection._
5+
import scala.collection.mutable.Buffer
56

67
opaque type IArray[+T] = Array[_ <: T]
78

@@ -39,9 +40,6 @@ object IArray:
3940
extension (arr: IArray[Object]) def length: Int = arr.asInstanceOf[Array[Object]].length
4041
extension [T](arr: IArray[T]) def length: Int = arr.asInstanceOf[Array[T]].length
4142

42-
/** Returns this array concatenated with the given array. */
43-
extension [T](arr: IArray[T]) def ++ [U >: T: ClassTag](that: IArray[U]): IArray[U] =
44-
genericArrayOps(arr) ++ that
4543

4644
/** Tests whether this array contains a given value as an element. */
4745
extension [T](arr: IArray[T]) def contains(elem: T): Boolean =
@@ -104,17 +102,17 @@ object IArray:
104102
genericArrayOps(arr).flatten
105103

106104
/** Folds the elements of this array using the specified associative binary operator. */
107-
extension [T](arr: IArray[T]) def fold[U >: T: ClassTag](z: U)(op: (U, U) => U): U =
105+
extension [T](arr: IArray[T]) def fold[U >: T](z: U)(op: (U, U) => U): U =
108106
genericArrayOps(arr).fold(z)(op)
109107

110108
/** Applies a binary operator to a start value and all elements of this array,
111109
* going left to right. */
112-
extension [T](arr: IArray[T]) def foldLeft[U: ClassTag](z: U)(op: (U, T) => U): U =
110+
extension [T](arr: IArray[T]) def foldLeft[U](z: U)(op: (U, T) => U): U =
113111
genericArrayOps(arr).foldLeft(z)(op)
114112

115113
/** Applies a binary operator to all elements of this array and a start value,
116114
* going right to left. */
117-
extension [T](arr: IArray[T]) def foldRight[U: ClassTag](z: U)(op: (T, U) => U): U =
115+
extension [T](arr: IArray[T]) def foldRight[U](z: U)(op: (T, U) => U): U =
118116
genericArrayOps(arr).foldRight(z)(op)
119117

120118
/** Tests whether a predicate holds for all elements of this array. */
@@ -217,7 +215,7 @@ object IArray:
217215

218216
/** Sorts this array according to the Ordering which results from transforming
219217
* an implicitly given Ordering with a transformation function. */
220-
extension [T](arr: IArray[T]) def sortBy[U: ClassTag](f: T => U)(using math.Ordering[U]): IArray[T] =
218+
extension [T](arr: IArray[T]) def sortBy[U](f: T => U)(using math.Ordering[U]): IArray[T] =
221219
genericArrayOps(arr).sortBy(f)
222220

223221
/** Sorts this array according to a comparison function. */
@@ -236,10 +234,6 @@ object IArray:
236234
extension [T](arr: IArray[T]) def splitAt(n: Int): (IArray[T], IArray[T]) =
237235
genericArrayOps(arr).splitAt(n)
238236

239-
/** Tests whether this array starts with the given array. */
240-
extension [T](arr: IArray[T]) def startsWith[U >: T: ClassTag](that: IArray[U], offset: Int = 0): Boolean =
241-
genericArrayOps(arr).startsWith(that)
242-
243237
/** The rest of the array without its first element. */
244238
extension [T](arr: IArray[T]) def tail: IArray[T] =
245239
genericArrayOps(arr).tail
@@ -264,11 +258,137 @@ object IArray:
264258
extension [U: ClassTag, V: ClassTag](arr: IArray[(U, V)]) def unzip: (IArray[U], IArray[V]) =
265259
genericArrayOps(arr).unzip
266260

267-
/** Returns an array formed from this array and another iterable collection
268-
* by combining corresponding elements in pairs.
269-
* If one of the two collections is longer than the other, its remaining elements are ignored. */
270-
extension [T](arr: IArray[T]) def zip[U: ClassTag](that: IArray[U]): IArray[(T, U)] =
271-
genericArrayOps(arr).zip(that)
261+
extension [A](arr: IArray[A])
262+
// def ++[B >: A: ClassTag](suffix: IArray[B]): IArray[B] = genericArrayOps(arr) ++ suffix.toSeq
263+
def ++[B >: A: ClassTag](suffix: IterableOnce[B]): IArray[B] = genericArrayOps(arr) ++ suffix
264+
def :+ [B >: A: ClassTag](x: B): IArray[B] = genericArrayOps(arr) :+ x
265+
// def :++ [B >: A: ClassTag](suffix: IArray[B]): IArray[B] = genericArrayOps(arr) :++ suffix
266+
def :++ [B >: A: ClassTag](suffix: IterableOnce[B]): IArray[B] = genericArrayOps(arr) :++ suffix
267+
def addString(b: mutable.StringBuilder): mutable.StringBuilder = arr.toSeq.addString(b)
268+
def addString(b: mutable.StringBuilder, sep: String): mutable.StringBuilder = arr.toSeq.addString(b, sep)
269+
def addString(b: mutable.StringBuilder, start: String, sep: String, end: String): mutable.StringBuilder = arr.toSeq.addString(b, start, sep, end)
270+
def appended[B >: A: ClassTag](x: B): IArray[B] = genericArrayOps(arr).appended(x)
271+
// def appendedAll[B >: A: ClassTag](suffix: IArray[B]): IArray[B] = genericArrayOps(arr).appendedAll(suffix)
272+
def appendedAll[B >: A: ClassTag](suffix: IterableOnce[B]): IArray[B] = genericArrayOps(arr).appendedAll(suffix)
273+
def collect[B: ClassTag](pf: PartialFunction[A, B]): IArray[B] = genericArrayOps(arr).collect(pf)
274+
def collectFirst[B](f: PartialFunction[A, B]): Option[B] = genericArrayOps(arr).collectFirst(f)
275+
def combinations(n: Int): Iterator[IArray[A]] = genericArrayOps(arr).combinations(n)
276+
// def concat[B >: A: ClassTag](suffix: IArray[B]): IArray[B] = genericArrayOps(arr).concat(suffix)
277+
def concat[B >: A: ClassTag](suffix: IterableOnce[B]): IArray[B] = genericArrayOps(arr).concat(suffix)
278+
// def containsSlice[B](that: IArray[B]): Boolean = arr.toSeq.containsSlice(that.toSeq)
279+
def containsSlice[B](that: Seq[B]): Boolean = arr.toSeq.containsSlice(that)
280+
// def corresponds[B](that: IArray[B])(p: (A, B) => Boolean): Boolean = arr.toSeq.corresponds(that.toSeq)(p)
281+
def corresponds[B](that: IterableOnce[B])(p: (A, B) => Boolean): Boolean = arr.toSeq.corresponds(that)(p)
282+
// def diff[B >: A](that: IArray[B]): IArray[A] = genericArrayOps(arr).diff(that.toSeq)
283+
def diff[B >: A](that: Seq[B]): IArray[A] = genericArrayOps(arr).diff(that)
284+
def distinct: IArray[A] = genericArrayOps(arr).distinct
285+
def distinctBy[B](f: A => B): IArray[A] = genericArrayOps(arr).distinctBy(f)
286+
def empty: immutable.ArraySeq[A] = arr.toSeq.empty
287+
// def startsWith[B >: A](that: IArray[B], offset: Int = 0): Boolean = genericArrayOps(arr).startsWith(that)
288+
def startsWith[B >: A](that: IterableOnce[B], offset: Int = 0): Boolean = genericArrayOps(arr).startsWith(that, offset)
289+
// def endsWith[B >: A](that: IArray[B]): Boolean = genericArrayOps(arr).endsWith(that)
290+
def endsWith[B >: A](that: Iterable[B]): Boolean = genericArrayOps(arr).endsWith(that)
291+
def findLast(p: A => Boolean): Option[A] = arr.toSeq.findLast(p)
292+
def groupBy[K](f: A => K): immutable.Map[K, IArray[A]] = genericArrayOps(arr).groupBy(f)
293+
def groupMap[K, B: ClassTag](key: A => K)(f: A => B): immutable.Map[K, IArray[B]] = genericArrayOps(arr).groupMap(key)(f)
294+
def groupMapReduce[K, B](key: (A) => K)(f: (A) => B)(reduce: (B, B) => B): immutable.Map[K, B] = arr.toSeq.groupMapReduce(key)(f)(reduce)
295+
def grouped(size: Int): Iterator[IArray[A]] = genericArrayOps(arr).grouped(size)
296+
// def indexOfSlice[B >: A](that: IArray[B]): Int = arr.toSeq.indexOfSlice(that)
297+
def indexOfSlice[B >: A](that: Seq[B]): Int = arr.toSeq.indexOfSlice(that)
298+
// def indexOfSlice[B >: A](that: IArray[B], from: Int): Int = arr.toSeq.indexOfSlice(that, from)
299+
def indexOfSlice[B >: A](that: Seq[B], from: Int): Int = arr.toSeq.indexOfSlice(that, from)
300+
def inits: Iterator[IArray[A]] = genericArrayOps(arr).inits
301+
// def intersect[B >: A](that: IArray[B]): IArray[A] = genericArrayOps(arr).intersect(that)
302+
def intersect[B >: A](that: Seq[B]): IArray[A] = genericArrayOps(arr).intersect(that)
303+
def isTraversableAgain: Boolean = arr.toSeq.isTraversableAgain
304+
def knownSize: Int = arr.length
305+
// def lastIndexOfSlice[B >: A](that: IArray[B]): Int = arr.toSeq.lastIndexOfSlice(that)
306+
def lastIndexOfSlice[B >: A](that: Seq[B]): Int = arr.toSeq.lastIndexOfSlice(that)
307+
// def lastIndexOfSlice[B >: A](that: IArray[B], end: Int): Int = arr.toSeq.lastIndexOfSlice(that, end)
308+
def lastIndexOfSlice[B >: A](that: Seq[B], end: Int): Int = arr.toSeq.lastIndexOfSlice(that, end)
309+
// def lazyZip[B](that: IArray[B]): LazyZip2[A, B, IArray[A]] = genericArrayOps(arr).lazyZip[B](that).asInstanceOf[LazyZip2[A, B, IArray[A]]]
310+
def lazyZip[B](that: Iterable[B]): LazyZip2[A, B, IArray[A]] = genericArrayOps(arr).lazyZip[B](that).asInstanceOf[LazyZip2[A, B, IArray[A]]]
311+
def lengthCompare(len: Int): Int = genericArrayOps(arr).lengthCompare(len)
312+
def lengthIs: IterableOps.SizeCompareOps = arr.toSeq.lengthIs
313+
def max[B >: A](using math.Ordering[B]): A = arr.toSeq.max[B]
314+
def maxBy[B](f: A => B)(using math.Ordering[B]): A = arr.toSeq.maxBy(f)
315+
def maxByOption[B](f: A => B)(using math.Ordering[B]): Option[A] = arr.toSeq.maxByOption(f)
316+
def maxOption[B >: A](using math.Ordering[B]): Option[B] = arr.toSeq.maxOption[B]
317+
def min[B >: A](using math.Ordering[B]): A = arr.toSeq.min[B]
318+
def minBy[B](f: A => B)(using math.Ordering[B]): A = arr.toSeq.minBy(f)
319+
def minByOption[B](f: A => B)(using math.Ordering[B]): Option[A] = arr.toSeq.minByOption(f)
320+
def minOption[B >: A](using math.Ordering[B]): Option[B] = arr.toSeq.minOption[B]
321+
def mkString: String = arr.toSeq.mkString
322+
def mkString(sep: String): String = arr.toSeq.mkString(sep)
323+
def mkString(start: String, sep: String, end: String): String = arr.toSeq.mkString(start, sep, end)
324+
def padTo[B >: A: ClassTag](len: Int, elem: B): IArray[B] = genericArrayOps(arr).padTo(len, elem)
325+
def partitionMap[A1: ClassTag, A2: ClassTag](f: A => Either[A1, A2]): (IArray[A1], IArray[A2]) = genericArrayOps(arr).partitionMap(f)
326+
def patch[B >: A: ClassTag](from: Int, other: IterableOnce[B], replaced: Int): IArray[B] = genericArrayOps(arr).patch(from, other, replaced)
327+
def permutations: Iterator[IArray[A]] = genericArrayOps(arr).permutations
328+
def prepended[B >: A: ClassTag](x: B): IArray[B] = genericArrayOps(arr).prepended(x)
329+
def prependedAll[B >: A: ClassTag](prefix: IterableOnce[B]): IArray[B] = genericArrayOps(arr).prependedAll(prefix)
330+
def product[B >: A](using math.Numeric[B]): B = arr.toSeq.product[B]
331+
def reduce[B >: A](op: (B, B) => B): B = arr.toSeq.reduce(op)
332+
def reduceLeft[B >: A](op: (B, A) => B): B = arr.toSeq.reduceLeft(op)
333+
def reduceRight[B >: A](op: (A, B) => B): B = arr.toSeq.reduceRight(op)
334+
def reverseIterator: Iterator[A] = genericArrayOps(arr).reverseIterator
335+
// def sameElements[B >: A](that: IArray[B]): Boolean = arr.toSeq.sameElements(that)
336+
def sameElements[B >: A](that: IterableOnce[B]): Boolean = arr.toSeq.sameElements(that)
337+
def search[B >: A](elem: B)(using Ordering[B]): Searching.SearchResult = arr.toSeq.search(elem)
338+
def search[B >: A](elem: B, from: Int, to: Int)(using Ordering[B]): Searching.SearchResult = arr.toSeq.search(elem, from, to)
339+
def segmentLength(p: (A) => Boolean, from: Int): Int = arr.toSeq.segmentLength(p, from)
340+
def segmentLength(p: (A) => Boolean): Int = arr.toSeq.segmentLength(p)
341+
// def sizeCompare(that: IArray[_]): Int = arr.toSeq.sizeCompare(that)
342+
def sizeCompare(that: Iterable[_]): Int = arr.toSeq.sizeCompare(that)
343+
def sizeCompare(otherSize: Int): Int = genericArrayOps(arr).sizeCompare(otherSize)
344+
def sizeIs: IterableOps.SizeCompareOps = arr.toSeq.sizeIs
345+
def sliding(size: Int, step: Int = 1): Iterator[IArray[A]] = genericArrayOps(arr).sliding(size, step)
346+
def stepper[S <: Stepper[_]](using StepperShape[A, S]): S = genericArrayOps(arr).stepper[S]
347+
def sum[B >: A](using math.Numeric[B]): B = arr.toSeq.sum[B]
348+
def tails: Iterator[IArray[A]] = genericArrayOps(arr).tails
349+
def tapEach[U](f: (A) => U): IArray[A] =
350+
arr.toSeq.foreach(f)
351+
arr
352+
def to[C1](factory: Factory[A, C1]): C1 = arr.toSeq.to(factory)
353+
def toBuffer[B >: A]: Buffer[B] = arr.toSeq.toBuffer[B]
354+
def toIndexedSeq: immutable.IndexedSeq[A] = arr.toSeq.toIndexedSeq
355+
def toIterable: Iterable[A] = arr.toSeq.toIterable
356+
def toList: List[A] = arr.toSeq.toList
357+
def toSet: Set[A] = arr.toSeq.toSet
358+
def toVector: Vector[A] = arr.toSeq.toVector
359+
def updated[B >: A: ClassTag](index: Int, elem: B): IArray[B] = genericArrayOps(arr).updated(index, elem)
360+
def view: SeqView[A] = genericArrayOps(arr).view
361+
// TODO: def withFilter(p: A => Boolean): ArrayOps.WithFilter[A] = genericArrayOps(arr).withFilter(p)
362+
// def zip[B](that: IArray[B]): IArray[(A, B)] = genericArrayOps(arr).zip(that)
363+
def zip[B](that: IterableOnce[B]): IArray[(A, B)] = genericArrayOps(arr).zip(that)
364+
// def zipAll[A1 >: A, B](that: IArray[B], thisElem: A1, thatElem: B): IArray[(A1, B)] = genericArrayOps(arr).zipAll(that, thisElem, thatElem)
365+
def zipAll[A1 >: A, B](that: Iterable[B], thisElem: A1, thatElem: B): IArray[(A1, B)] = genericArrayOps(arr).zipAll(that, thisElem, thatElem)
366+
def zipWithIndex: IArray[(A, Int)] = genericArrayOps(arr).zipWithIndex
367+
end extension
368+
369+
extension [A: ClassTag](arr: IArray[IterableOnce[A]])
370+
def flatten: IArray[A] = genericArrayOps(arr).flatten
371+
372+
extension [A, B >: A: ClassTag](prefix: IterableOnce[A])
373+
def ++:(arr: IArray[B]): IArray[B] = genericArrayOps(arr).prependedAll(prefix)
374+
375+
extension [A, B >: A: ClassTag](prefix: IArray[A])
376+
def ++:(arr: IArray[B]): IArray[B] = genericArrayOps(arr).prependedAll(prefix)
377+
378+
extension [A, B >: A: ClassTag](x: A)
379+
def +:(arr: IArray[B]): IArray[B] = genericArrayOps(arr).prepended(x)
380+
381+
382+
extension [A1, A2](arr: IArray[(A1, A2)])
383+
def toMap: Map[A1, A2] = arr.toSeq.toMap
384+
385+
extension [A1: ClassTag, A2: ClassTag, A3: ClassTag](arr: IArray[(A1, A2, A3)])
386+
def unzip3: (IArray[A1], IArray[A2], IArray[A3]) = genericArrayOps(arr).unzip3
387+
388+
// TODO
389+
// extension [A](arr: IArray[IArray[A]])
390+
// def transpose[B](implicit asArray: A => Array[B]): IArray[IArray[B]] =
391+
// genericArrayOps(arr).transpose(using asArray.asInstanceOf)
272392

273393
/** Conversion from IArray to immutable.ArraySeq */
274394
extension [T](arr: IArray[T]) def toSeq: immutable.ArraySeq[T] =
@@ -372,7 +492,7 @@ object IArray:
372492
// `Array.concat` should arguably take in a `Seq[Array[_ <: T]]`,
373493
// but since it currently takes a `Seq[Array[T]]` we have to perform a cast,
374494
// knowing tacitly that `concat` is not going to do the wrong thing.
375-
Array.concat[T](xss.asInstanceOf[Seq[Array[T]]]: _*)
495+
Array.concat[T](xss.asInstanceOf[immutable.Seq[Array[T]]]: _*)
376496

377497
/** Returns an immutable array that contains the results of some element computation a number
378498
* of times. Each element is determined by a separate computation.
@@ -521,4 +641,4 @@ object IArray:
521641
def unapplySeq[T](x: IArray[T]): Array.UnapplySeqWrapper[_ <: T] =
522642
Array.unapplySeq(x)
523643

524-
end IArray
644+
end IArray

tests/run/IArrayOps.check

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
ArraySeq(1, 2, 3)
2+
true
3+
false
4+
ArraySeq(1, 9, 3)
5+
ArraySeq(1, a, 3)
6+
ArraySeq(1, 2, 3, 0)
7+
ArraySeq(1, 1, 2, 3)
8+
ArraySeq(1, 5, 4, 3)
9+
1
10+
1
11+
ArraySeq(1, 5, 4, 3)
12+
ArraySeq(5, 4, 3)
13+
ArraySeq()
14+
ArraySeq(1, 2, 3, 5, 4, 5, 6)
15+
ArraySeq(1, 2, 3, 7)
16+
ArraySeq(8, 1, 2, 3)
17+
ArraySeq(5, 4, 5, 6, 12, 13, 14)
18+
ArraySeq(12, 13, 14, 5, 4, 5, 6)
19+
123
20+
1-2-3
21+
(1,2,3)
22+
ArraySeq(1, 2, 3, 5)
23+
ArraySeq(1, 2, 3, 1, 4)
24+
ArraySeq(5, 1, 2, 3)
25+
ArraySeq(5, 6, 1, 2, 3)
26+
ArraySeq(2, 6)
27+
Some(2)
28+
List(ArraySeq(1), ArraySeq(2), ArraySeq(3))
29+
List(ArraySeq(1, 2), ArraySeq(1, 3), ArraySeq(2, 3))
30+
List(ArraySeq(1, 2, 3))
31+
ArraySeq(1, 2, 3, 8, 9)
32+
true
33+
true
34+
false
35+
ArraySeq(3)
36+
ArraySeq(3)
37+
ArraySeq(1, 2, 3)
38+
ArraySeq(5, 4, 6)
39+
ArraySeq(5, 4)
40+
false
41+
true
42+
Some(1)
43+
Some(2)
44+
6
45+
6
46+
6
47+
6
48+
6
49+
6
50+
Map(1 -> ArraySeq(1), 2 -> ArraySeq(2), 3 -> ArraySeq(3))
51+
Map(0 -> ArraySeq(2), 1 -> ArraySeq(1, 3))
52+
Map(1 -> ArraySeq(1), 2 -> ArraySeq(2), 3 -> ArraySeq(3))
53+
Map(0 -> ArraySeq(2), 1 -> ArraySeq(1, 3))
54+
Map(1 -> 1, 2 -> 2, 3 -> 3)
55+
Map(0 -> 2, 1 -> 13)
56+
List(ArraySeq(1, 2), ArraySeq(3))
57+
0
58+
1
59+
-1
60+
1
61+
0
62+
1
63+
0
64+
1
65+
List(ArraySeq(1, 2, 3), ArraySeq(1, 2), ArraySeq(1), ArraySeq())
66+
List(ArraySeq(1, 2, 3), ArraySeq(2, 3), ArraySeq(3), ArraySeq())
67+
ArraySeq(1, 2)
68+
ArraySeq(2, 3)
69+
3
70+
ArraySeq(1, 2, 3).lazyZip(ArraySeq(5, 4, 5, 6))
71+
List((1,5), (2,4), (3,5))
72+
0
73+
1
74+
-1
75+
3
76+
Some(3)
77+
3
78+
Some(3)
79+
1
80+
Some(1)
81+
1
82+
Some(1)
83+
123
84+
1-2-3
85+
(1,2,3)
86+
ArraySeq((1,5), (2,4), (3,5))
87+
ArraySeq((1,5), (2,5), (3,5))
88+
ArraySeq((1,5), (2,5), (3,4))
89+
ArraySeq(1, 2)
90+
ArraySeq(a, b)
91+
ArraySeq(1, 2)
92+
ArraySeq(a, b)
93+
ArraySeq(x, y)
94+
ArraySeq(1, 2, 3, 0, 0, 0)
95+
ArraySeq(1, 2, 3)
96+
ArraySeq()
97+
ArraySeq()
98+
ArraySeq(1, 2, 3)
99+
ArraySeq(1, 6, 7, 8, 9)
100+
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))
101+
6
102+
6
103+
List(1, 2, 3)
104+
List(3, 2, 1)
105+
true
106+
false
107+
1
108+
0
109+
-1
110+
1
111+
List(ArraySeq(1, 2), ArraySeq(2, 3))
112+
List(ArraySeq(5, 4, 5), ArraySeq(5, 6))
113+
ArraySeq(6, 5, 5, 4)
114+
true
115+
true
116+
1
117+
2
118+
3
119+
ArraySeq(1, 2, 3)
120+
ArraySeq((1,0), (2,1), (3,2))
121+
List(1, 2, 3)
122+
Vector(1, 2, 3)
123+
ArrayBuffer(1, 2, 3)
124+
ArraySeq(1, 2, 3)
125+
ArraySeq(1, 2, 3)
126+
List(1, 2, 3)
127+
Set(1, 2, 3)
128+
Vector(1, 2, 3)
129+
ArrayView(1, 2, 3)
130+
Map(1 -> 5, 2 -> 4, 3 -> 5)
131+
ArraySeq()
132+
true
133+
false
134+
false
135+
ArraySeq(1, 2, 2, 3)
136+
Found(1)
137+
InsertionPoint(2)

0 commit comments

Comments
 (0)