0
# Immutable Collections
1
2
High-performance immutable arrays with covariant types and comprehensive collection operations, providing JavaScript-optimized implementations of standard collection patterns.
3
4
## Capabilities
5
6
### IArray - Immutable Arrays
7
8
Covariant immutable arrays with complete collection API and primitive specializations.
9
10
```scala { .api }
11
/**
12
* Immutable array with covariant type parameter
13
* Provides O(1) access with immutable semantics
14
*/
15
opaque type IArray[+T] = Array[? <: T]
16
17
object IArray:
18
/** Create empty IArray */
19
def empty[T]: IArray[T]
20
21
/** Create IArray from elements */
22
def apply[T](elems: T*): IArray[T]
23
24
/** Create IArray with repeated element */
25
def fill[T](n: Int)(elem: => T): IArray[T]
26
27
/** Create IArray using index function */
28
def tabulate[T](n: Int)(f: Int => T): IArray[T]
29
30
/** Create IArray with range of integers */
31
def range(start: Int, end: Int): IArray[Int]
32
def range(start: Int, end: Int, step: Int): IArray[Int]
33
34
/** Create IArray from iterable */
35
def from[T](it: IterableOnce[T]): IArray[T]
36
37
/** Concatenate multiple IArrays */
38
def concat[T](arrays: IArray[T]*): IArray[T]
39
40
/**
41
* Extension methods for IArray instances
42
*/
43
extension [T](arr: IArray[T])
44
// Access operations
45
/** Get element at index */
46
def apply(index: Int): T
47
/** Get array length */
48
def length: Int
49
/** Check if array is empty */
50
def isEmpty: Boolean
51
/** Check if array is non-empty */
52
def nonEmpty: Boolean
53
/** Get indices range */
54
def indices: Range
55
56
// Element access
57
/** Get first element (unsafe) */
58
def head: T
59
/** Get first element safely */
60
def headOption: Option[T]
61
/** Get last element (unsafe) */
62
def last: T
63
/** Get last element safely */
64
def lastOption: Option[T]
65
/** Get all elements except first */
66
def tail: IArray[T]
67
/** Get all elements except last */
68
def init: IArray[T]
69
70
// Transformation operations
71
/** Transform each element */
72
def map[U](f: T => U): IArray[U]
73
/** Transform with index */
74
def mapWithIndex[U](f: (T, Int) => U): IArray[U]
75
/** Flat map transformation */
76
def flatMap[U](f: T => IterableOnce[U]): IArray[U]
77
/** Filter elements */
78
def filter(p: T => Boolean): IArray[T]
79
/** Filter with negation */
80
def filterNot(p: T => Boolean): IArray[T]
81
/** Collect partial function results */
82
def collect[U](pf: PartialFunction[T, U]): IArray[U]
83
84
// Slicing operations
85
/** Take first n elements */
86
def take(n: Int): IArray[T]
87
/** Drop first n elements */
88
def drop(n: Int): IArray[T]
89
/** Take while predicate holds */
90
def takeWhile(p: T => Boolean): IArray[T]
91
/** Drop while predicate holds */
92
def dropWhile(p: T => Boolean): IArray[T]
93
/** Take right n elements */
94
def takeRight(n: Int): IArray[T]
95
/** Drop right n elements */
96
def dropRight(n: Int): IArray[T]
97
/** Get slice between indices */
98
def slice(from: Int, until: Int): IArray[T]
99
/** Split at index */
100
def splitAt(n: Int): (IArray[T], IArray[T])
101
102
// Combination operations
103
/** Concatenate with another IArray */
104
def concat[U >: T](that: IArray[U]): IArray[U]
105
def ++[U >: T](that: IArray[U]): IArray[U]
106
/** Prepend element */
107
def prepended[U >: T](elem: U): IArray[U]
108
/** Append element */
109
def appended[U >: T](elem: U): IArray[U]
110
/** Prepend elements */
111
def prependedAll[U >: T](prefix: IterableOnce[U]): IArray[U]
112
/** Append elements */
113
def appendedAll[U >: T](suffix: IterableOnce[U]): IArray[U]
114
115
// Searching operations
116
/** Find element matching predicate */
117
def find(p: T => Boolean): Option[T]
118
/** Check if element exists */
119
def exists(p: T => Boolean): Boolean
120
/** Check if all elements match */
121
def forall(p: T => Boolean): Boolean
122
/** Check if contains element */
123
def contains[U >: T](elem: U): Boolean
124
/** Find index of element */
125
def indexOf[U >: T](elem: U): Int
126
def indexOf[U >: T](elem: U, from: Int): Int
127
/** Find last index of element */
128
def lastIndexOf[U >: T](elem: U): Int
129
def lastIndexOf[U >: T](elem: U, end: Int): Int
130
/** Find index where predicate holds */
131
def indexWhere(p: T => Boolean): Int
132
def indexWhere(p: T => Boolean, from: Int): Int
133
134
// Sorting operations
135
/** Sort elements */
136
def sorted[U >: T](using Ordering[U]): IArray[U]
137
/** Sort by key */
138
def sortBy[U](f: T => U)(using Ordering[U]): IArray[T]
139
/** Sort with custom comparator */
140
def sortWith(lt: (T, T) => Boolean): IArray[T]
141
142
// Grouping operations
143
/** Remove duplicate elements */
144
def distinct: IArray[T]
145
/** Remove duplicates by key */
146
def distinctBy[U](f: T => U): IArray[T]
147
/** Group by key */
148
def groupBy[K](f: T => K): Map[K, IArray[T]]
149
/** Group consecutive equal elements */
150
def groupMap[K, V](key: T => K)(f: T => V): Map[K, IArray[V]]
151
/** Partition by predicate */
152
def partition(p: T => Boolean): (IArray[T], IArray[T])
153
/** Span while predicate holds */
154
def span(p: T => Boolean): (IArray[T], IArray[T])
155
156
// Aggregation operations
157
/** Fold left */
158
def foldLeft[U](z: U)(op: (U, T) => U): U
159
/** Fold right */
160
def foldRight[U](z: U)(op: (T, U) => U): U
161
/** Reduce left */
162
def reduceLeft[U >: T](op: (U, T) => U): U
163
/** Reduce right */
164
def reduceRight[U >: T](op: (T, U) => U): U
165
/** Reduce with option */
166
def reduceLeftOption[U >: T](op: (U, T) => U): Option[U]
167
def reduceRightOption[U >: T](op: (T, U) => U): Option[U]
168
/** Aggregate/combine */
169
def aggregate[U](z: => U)(seqop: (U, T) => U, combop: (U, U) => U): U
170
171
// Conversion operations
172
/** Convert to Array */
173
def toArray[U >: T : ClassTag]: Array[U]
174
/** Convert to List */
175
def toList: List[T]
176
/** Convert to Vector */
177
def toVector: Vector[T]
178
/** Convert to Set */
179
def toSet: Set[T]
180
/** Convert to Map with indices */
181
def toMap[K, V](using ev: T <:< (K, V)): Map[K, V]
182
/** Convert to mutable buffer */
183
def toBuffer: mutable.Buffer[T]
184
185
// Zipping operations
186
/** Zip with another collection */
187
def zip[U](that: IArray[U]): IArray[(T, U)]
188
/** Zip with indices */
189
def zipWithIndex: IArray[(T, Int)]
190
/** Zip all with filler values */
191
def zipAll[U, V >: T](that: IArray[U], thisElem: V, thatElem: U): IArray[(V, U)]
192
193
// Utility operations
194
/** Apply side effect to each element */
195
def foreach[U](f: T => U): Unit
196
/** Reverse array order */
197
def reverse: IArray[T]
198
/** Get string representation */
199
def mkString: String
200
def mkString(sep: String): String
201
def mkString(start: String, sep: String, end: String): String
202
/** Get element count */
203
def count(p: T => Boolean): Int
204
/** Check if corresponds to another collection */
205
def corresponds[U](that: IterableOnce[U])(p: (T, U) => Boolean): Boolean
206
```
207
208
**Usage Examples:**
209
210
```scala
211
import scala.IArray
212
213
// Creating IArrays
214
val numbers = IArray(1, 2, 3, 4, 5)
215
val empty = IArray.empty[String]
216
val filled = IArray.fill(3)("default")
217
val computed = IArray.tabulate(5)(i => i * i)
218
val range = IArray.range(1, 10)
219
220
// Basic operations
221
println(numbers.length) // 5
222
println(numbers.head) // 1
223
println(numbers.last) // 5
224
println(numbers.isEmpty) // false
225
226
// Transformations
227
val doubled = numbers.map(_ * 2)
228
val evens = numbers.filter(_ % 2 == 0)
229
val squares = numbers.map(x => x * x)
230
231
// Slicing
232
val first3 = numbers.take(3) // IArray(1, 2, 3)
233
val without2 = numbers.drop(2) // IArray(3, 4, 5)
234
val middle = numbers.slice(1, 4) // IArray(2, 3, 4)
235
236
// Searching
237
val found = numbers.find(_ > 3) // Some(4)
238
val index = numbers.indexOf(3) // 2
239
val contains4 = numbers.contains(4) // true
240
241
// Sorting
242
val names = IArray("Charlie", "Alice", "Bob")
243
val sorted = names.sorted // IArray("Alice", "Bob", "Charlie")
244
val byLength = names.sortBy(_.length) // IArray("Bob", "Alice", "Charlie")
245
246
// Aggregation
247
val sum = numbers.foldLeft(0)(_ + _) // 15
248
val max = numbers.reduceLeft(_ max _) // 5
249
val product = numbers.reduce(_ * _) // 120
250
251
// Grouping
252
val data = IArray("apple", "banana", "apricot", "cherry")
253
val byFirstLetter = data.groupBy(_.head)
254
// Map('a' -> IArray("apple", "apricot"), 'b' -> IArray("banana"), 'c' -> IArray("cherry"))
255
256
// Combinations
257
val moreNumbers = IArray(6, 7, 8)
258
val combined = numbers ++ moreNumbers // IArray(1, 2, 3, 4, 5, 6, 7, 8)
259
val withZero = numbers.prepended(0) // IArray(0, 1, 2, 3, 4, 5)
260
261
// Zipping
262
val letters = IArray("a", "b", "c", "d", "e")
263
val pairs = numbers.zip(letters) // IArray((1,"a"), (2,"b"), (3,"c"), (4,"d"), (5,"e"))
264
val indexed = numbers.zipWithIndex // IArray((1,0), (2,1), (3,2), (4,3), (5,4))
265
266
// Conversions
267
val asList = numbers.toList
268
val asVector = numbers.toVector
269
val asArray = numbers.toArray
270
val asSet = numbers.toSet
271
```
272
273
### Specialized IArray Types
274
275
IArray provides specialized implementations for primitive types for better performance.
276
277
```scala { .api }
278
// Specialized factory methods
279
object IArray:
280
/** Create specialized boolean array */
281
def ofBoolean(elems: Boolean*): IArray[Boolean]
282
/** Create specialized byte array */
283
def ofByte(elems: Byte*): IArray[Byte]
284
/** Create specialized short array */
285
def ofShort(elems: Short*): IArray[Short]
286
/** Create specialized char array */
287
def ofChar(elems: Char*): IArray[Char]
288
/** Create specialized int array */
289
def ofInt(elems: Int*): IArray[Int]
290
/** Create specialized long array */
291
def ofLong(elems: Long*): IArray[Long]
292
/** Create specialized float array */
293
def ofFloat(elems: Float*): IArray[Float]
294
/** Create specialized double array */
295
def ofDouble(elems: Double*): IArray[Double]
296
```
297
298
**Usage Examples:**
299
300
```scala
301
// Specialized arrays for better performance
302
val ints = IArray.ofInt(1, 2, 3, 4, 5)
303
val doubles = IArray.ofDouble(1.0, 2.5, 3.14)
304
val booleans = IArray.ofBoolean(true, false, true)
305
306
// All operations work the same
307
val doubled = ints.map(_ * 2)
308
val filtered = doubles.filter(_ > 2.0)
309
val count = booleans.count(identity)
310
```
311
312
### Multi-dimensional Arrays
313
314
Support for creating and working with multi-dimensional immutable arrays.
315
316
```scala { .api }
317
object IArray:
318
/** Create 2D array */
319
def ofDim[T](dim1: Int, dim2: Int): IArray[IArray[T]]
320
/** Create 3D array */
321
def ofDim[T](dim1: Int, dim2: Int, dim3: Int): IArray[IArray[IArray[T]]]
322
323
/** Fill 2D array */
324
def fill[T](dim1: Int, dim2: Int)(elem: => T): IArray[IArray[T]]
325
/** Fill 3D array */
326
def fill[T](dim1: Int, dim2: Int, dim3: Int)(elem: => T): IArray[IArray[IArray[T]]]
327
328
/** Tabulate 2D array */
329
def tabulate[T](dim1: Int, dim2: Int)(f: (Int, Int) => T): IArray[IArray[T]]
330
/** Tabulate 3D array */
331
def tabulate[T](dim1: Int, dim2: Int, dim3: Int)(f: (Int, Int, Int) => T): IArray[IArray[IArray[T]]]
332
```
333
334
**Usage Examples:**
335
336
```scala
337
// 2D matrix
338
val matrix = IArray.tabulate(3, 3)((i, j) => i * 3 + j)
339
// IArray(IArray(0, 1, 2), IArray(3, 4, 5), IArray(6, 7, 8))
340
341
// Access elements
342
val element = matrix(1)(2) // 5
343
344
// 3D tensor
345
val tensor = IArray.fill(2, 2, 2)(0)
346
```
347
348
## Types
349
350
```scala { .api }
351
// Core immutable array type
352
opaque type IArray[+T] = Array[? <: T]
353
354
// Companion object with factory methods
355
object IArray:
356
def empty[T]: IArray[T]
357
def apply[T](elems: T*): IArray[T]
358
def fill[T](n: Int)(elem: => T): IArray[T]
359
def tabulate[T](n: Int)(f: Int => T): IArray[T]
360
def range(start: Int, end: Int): IArray[Int]
361
def range(start: Int, end: Int, step: Int): IArray[Int]
362
def from[T](it: IterableOnce[T]): IArray[T]
363
def concat[T](arrays: IArray[T]*): IArray[T]
364
365
// Specialized factory methods
366
def ofBoolean(elems: Boolean*): IArray[Boolean]
367
def ofByte(elems: Byte*): IArray[Byte]
368
def ofShort(elems: Short*): IArray[Short]
369
def ofChar(elems: Char*): IArray[Char]
370
def ofInt(elems: Int*): IArray[Int]
371
def ofLong(elems: Long*): IArray[Long]
372
def ofFloat(elems: Float*): IArray[Float]
373
def ofDouble(elems: Double*): IArray[Double]
374
375
// Multi-dimensional arrays
376
def ofDim[T](dim1: Int, dim2: Int): IArray[IArray[T]]
377
def ofDim[T](dim1: Int, dim2: Int, dim3: Int): IArray[IArray[IArray[T]]]
378
```