Skip to content

Commit af2a0e6

Browse files
committed
Add immutable array type
IArray[T] is an opaque alias for Array[T]
1 parent d7eafe1 commit af2a0e6

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package scala
2+
import reflect.ClassTag
3+
4+
/** It would be nice it IArray could be covariant, but unfortunately that's not
5+
* possible. The problem is the preculiar behavior of `Array[Any]`.
6+
* `Array[Any]` erases to `Object[]`. So, `IArray[Any]` also erases to `Object[]`.
7+
* Bit this means `IArray[Int]`, which erases to `Int[]`, cannot be a subtype of
8+
* `IArray[Any]`.
9+
*/
10+
opaque type IArray[T] = Array[T]
11+
12+
object IArray {
13+
14+
implied arrayOps {
15+
inline def (arr: IArray[T]) apply[T] (n: Int): T = (arr: Array[T]).apply(n)
16+
inline def (arr: IArray[T]) length[T] : Int = (arr: Array[T]).length
17+
}
18+
def apply[T: ClassTag](xs: T*): IArray[T] = Array(xs: _*)
19+
20+
def apply(x: Boolean, xs: Boolean*): IArray[Boolean] = Array(x, xs: _*)
21+
def apply(x: Byte, xs: Byte*): IArray[Byte] = Array(x, xs: _*)
22+
def apply(x: Short, xs: Short*): IArray[Short] = Array(x, xs: _*)
23+
def apply(x: Char, xs: Char*): IArray[Char] = Array(x, xs: _*)
24+
def apply(x: Int, xs: Int*): IArray[Int] = Array(x, xs: _*)
25+
def apply(x: Long, xs: Long*): IArray[Long] = Array(x, xs: _*)
26+
def apply(x: Float, xs: Float*): IArray[Float] = Array(x, xs: _*)
27+
def apply(x: Double, xs: Double*): IArray[Double] = Array(x, xs: _*)
28+
def apply(x: Unit, xs: Unit*): IArray[Unit] = Array(x, xs: _*)
29+
30+
def concat[T: ClassTag](xss: IArray[T]*): IArray[T] = Array.concat(xss: _*)
31+
32+
def fill[T: ClassTag](n: Int)(elem: => T): IArray[T] =
33+
Array.fill(n)(elem)
34+
def fill[T: ClassTag](n1: Int, n2: Int)(elem: => T): IArray[IArray[T]] =
35+
Array.fill(n1, n2)(elem)
36+
def fill[T: ClassTag](n1: Int, n2: Int, n3: Int)(elem: => T): IArray[IArray[IArray[T]]] =
37+
Array.fill(n1, n2, n3)(elem)
38+
def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): IArray[IArray[IArray[IArray[T]]]] =
39+
Array.fill(n1, n2, n3, n4)(elem)
40+
def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): IArray[IArray[IArray[IArray[IArray[T]]]]] =
41+
Array.fill(n1, n2, n3, n4, n5)(elem)
42+
43+
def tabulate[T: ClassTag](n: Int)(f: Int => T): IArray[T] =
44+
Array.tabulate(n)(f)
45+
def tabulate[T: ClassTag](n1: Int, n2: Int)(f: (Int, Int) => T): IArray[IArray[T]] =
46+
Array.tabulate(n1, n2)(f)
47+
def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): IArray[IArray[IArray[T]]] =
48+
Array.tabulate(n1, n2, n3)(f)
49+
def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): IArray[IArray[IArray[IArray[T]]]] =
50+
Array.tabulate(n1, n2, n3, n4)(f)
51+
def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): IArray[IArray[IArray[IArray[IArray[T]]]]] =
52+
Array.tabulate(n1, n2, n3, n4, n5)(f)
53+
54+
def range(start: Int, end: Int): IArray[Int] = Array.range(start, end)
55+
def range(start: Int, end: Int, step: Int): IArray[Int] = Array.range(start, end, step)
56+
57+
def iterate[T: ClassTag](start: T, len: Int)(f: T => T): IArray[T] = Array.iterate(start, len)(f)
58+
59+
def unapplySeq[T](x: IArray[T]): Option[IndexedSeq[T]] = Array.unapplySeq(x)
60+
}

tests/run/iarrays.scala

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import reflect.ClassTag
2+
object Test extends App {
3+
4+
val xs = IArray(1, 2, 3)
5+
6+
def f[T](ys: IArray[T]) = {
7+
assert(ys.length == 3)
8+
var sum = 0
9+
for (i <- 0 until ys.length)
10+
sum += xs(i)
11+
assert(sum == 6)
12+
}
13+
14+
f(xs)
15+
16+
var sum = 0
17+
for (i <- 0 until xs.length)
18+
sum += xs(i)
19+
assert(sum == 6)
20+
21+
def reduce[T](xs: IArray[T], z: T, op: (T, T) => T) = {
22+
var acc = z
23+
for (i <- 0 until xs.length)
24+
acc = op(acc, xs(i))
25+
acc
26+
}
27+
28+
def flatten[T: ClassTag](ys: IArray[IArray[T]]) = {
29+
var len = 0
30+
for (i <- 0 until ys.length) len += ys(i).length
31+
val flat = new Array[T](len)
32+
var k = 0
33+
for (i <- 0 until ys.length) {
34+
for (j <- 0 until ys(i).length) {
35+
flat(k) = ys(i)(j)
36+
k += 1
37+
}
38+
}
39+
IArray(flat: _*)
40+
}
41+
42+
val ys = IArray.concat(xs, xs, xs)
43+
assert(reduce(ys, 0, _ + _) == 18)
44+
45+
val zss = IArray.fill(2, 3)(1)
46+
val zs = flatten(zss)
47+
assert(reduce(zs, 0, _ + _) == 6)
48+
49+
val is = IArray.iterate(0, 4)(_ + 1)
50+
assert(reduce(is, 0, _ + _) == 6)
51+
52+
val IArray(1, 2, 3) = xs
53+
}

0 commit comments

Comments
 (0)