Skip to content

Commit 79743c7

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

File tree

3 files changed

+445
-13
lines changed

3 files changed

+445
-13
lines changed

library/src/scala/IArray.scala

Lines changed: 118 additions & 13 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

@@ -104,17 +105,17 @@ object IArray:
104105
genericArrayOps(arr).flatten
105106

106107
/** 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 =
108+
extension [T](arr: IArray[T]) def fold[U >: T](z: U)(op: (U, U) => U): U =
108109
genericArrayOps(arr).fold(z)(op)
109110

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

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

120121
/** Tests whether a predicate holds for all elements of this array. */
@@ -217,7 +218,7 @@ object IArray:
217218

218219
/** Sorts this array according to the Ordering which results from transforming
219220
* 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] =
221+
extension [T](arr: IArray[T]) def sortBy[U](f: T => U)(using math.Ordering[U]): IArray[T] =
221222
genericArrayOps(arr).sortBy(f)
222223

223224
/** Sorts this array according to a comparison function. */
@@ -237,7 +238,7 @@ object IArray:
237238
genericArrayOps(arr).splitAt(n)
238239

239240
/** 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+
extension [T](arr: IArray[T]) def startsWith[U >: T](that: IArray[U], offset: Int = 0): Boolean =
241242
genericArrayOps(arr).startsWith(that)
242243

243244
/** The rest of the array without its first element. */
@@ -264,11 +265,115 @@ object IArray:
264265
extension [U: ClassTag, V: ClassTag](arr: IArray[(U, V)]) def unzip: (IArray[U], IArray[V]) =
265266
genericArrayOps(arr).unzip
266267

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

273378
/** Conversion from IArray to immutable.ArraySeq */
274379
extension [T](arr: IArray[T]) def toSeq: immutable.ArraySeq[T] =
@@ -372,7 +477,7 @@ object IArray:
372477
// `Array.concat` should arguably take in a `Seq[Array[_ <: T]]`,
373478
// but since it currently takes a `Seq[Array[T]]` we have to perform a cast,
374479
// knowing tacitly that `concat` is not going to do the wrong thing.
375-
Array.concat[T](xss.asInstanceOf[Seq[Array[T]]]: _*)
480+
Array.concat[T](xss.asInstanceOf[immutable.Seq[Array[T]]]: _*)
376481

377482
/** Returns an immutable array that contains the results of some element computation a number
378483
* of times. Each element is determined by a separate computation.
@@ -521,4 +626,4 @@ object IArray:
521626
def unapplySeq[T](x: IArray[T]): Array.UnapplySeqWrapper[_ <: T] =
522627
Array.unapplySeq(x)
523628

524-
end IArray
629+
end IArray

tests/run/IArrayOps.check

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

0 commit comments

Comments
 (0)