or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdcompile-time.mdgeneric-programming.mdimmutable-arrays.mdindex.mdmacros.mdstructural-types.mdtuples.mdtype-safe-equality.md

immutable-arrays.mddocs/

0

# Immutable Arrays

1

2

`IArray` provides covariant immutable arrays with rich collection operations, combining the performance characteristics of arrays with immutability guarantees.

3

4

## Core API

5

6

### IArray Type

7

8

```scala { .api }

9

opaque type IArray[+T] = Array[? <: T]

10

```

11

12

An immutable array that has the same representation as `Array[T]` but cannot be updated. Unlike regular arrays, immutable arrays are covariant.

13

14

### Element Access

15

16

```scala { .api }

17

extension (arr: IArray[Byte]) def apply(n: Int): Byte

18

extension (arr: IArray[Short]) def apply(n: Int): Short

19

extension (arr: IArray[Char]) def apply(n: Int): Char

20

extension (arr: IArray[Int]) def apply(n: Int): Int

21

extension (arr: IArray[Long]) def apply(n: Int): Long

22

extension (arr: IArray[Float]) def apply(n: Int): Float

23

extension (arr: IArray[Double]) def apply(n: Int): Double

24

extension [T <: Object](arr: IArray[T]) def apply(n: Int): T

25

extension [T](arr: IArray[T]) def apply(n: Int): T

26

```

27

28

Specialized element access methods for primitive types and generic access for all types.

29

30

### Size Operations

31

32

```scala { .api }

33

extension [T](arr: IArray[T]):

34

def length: Int

35

def size: Int

36

def isEmpty: Boolean

37

def nonEmpty: Boolean

38

def indices: Range

39

```

40

41

Basic size and emptiness checking operations.

42

43

## Transformation Operations

44

45

### Mapping and Filtering

46

47

```scala { .api }

48

extension [T](arr: IArray[T]):

49

def map[U: ClassTag](f: T => U): IArray[U]

50

def flatMap[U: ClassTag](f: T => IterableOnce[U]): IArray[U]

51

def filter(p: T => Boolean): IArray[T]

52

def filterNot(p: T => Boolean): IArray[T]

53

def collect[U: ClassTag](pf: PartialFunction[T, U]): IArray[U]

54

```

55

56

Standard functional operations that return new immutable arrays.

57

58

### Scanning and Folding

59

60

```scala { .api }

61

extension [T](arr: IArray[T]):

62

def scan[U >: T: ClassTag](z: U)(op: (U, U) => U): IArray[U]

63

def scanLeft[U: ClassTag](z: U)(op: (U, T) => U): IArray[U]

64

def scanRight[U: ClassTag](z: U)(op: (T, U) => U): IArray[U]

65

def fold[U >: T](z: U)(op: (U, U) => U): U

66

def foldLeft[U](z: U)(op: (U, T) => U): U

67

def foldRight[U](z: U)(op: (T, U) => U): U

68

```

69

70

Accumulation operations for computing single values or progressive results.

71

72

## Slicing and Selection

73

74

### Element Selection

75

76

```scala { .api }

77

extension [T](arr: IArray[T]):

78

def head: T

79

def headOption: Option[T]

80

def last: T

81

def lastOption: Option[T]

82

def tail: IArray[T]

83

def init: IArray[T]

84

```

85

86

Operations for accessing first, last, and boundary elements.

87

88

### Slicing Operations

89

90

```scala { .api }

91

extension [T](arr: IArray[T]):

92

def take(n: Int): IArray[T]

93

def takeRight(n: Int): IArray[T]

94

def takeWhile(p: T => Boolean): IArray[T]

95

def drop(n: Int): IArray[T]

96

def dropRight(n: Int): IArray[T]

97

def dropWhile(p: T => Boolean): IArray[T]

98

def slice(from: Int, until: Int): IArray[T]

99

def splitAt(n: Int): (IArray[T], IArray[T])

100

```

101

102

Operations for extracting subsequences and splitting arrays.

103

104

## Search and Query Operations

105

106

### Element Search

107

108

```scala { .api }

109

extension [T](arr: IArray[T]):

110

def contains(elem: T): Boolean

111

def indexOf(elem: T, from: Int = 0): Int

112

def lastIndexOf(elem: T, end: Int = arr.length - 1): Int

113

def indexWhere(p: T => Boolean, from: Int = 0): Int

114

def lastIndexWhere(p: T => Boolean, end: Int = arr.length - 1): Int

115

```

116

117

Methods for finding elements and their positions.

118

119

### Predicate Testing

120

121

```scala { .api }

122

extension [T](arr: IArray[T]):

123

def exists(p: T => Boolean): Boolean

124

def forall(p: T => Boolean): Boolean

125

def find(p: T => Boolean): Option[T]

126

def count(p: T => Boolean): Int

127

```

128

129

Testing elements against predicates.

130

131

## Combination Operations

132

133

### Array Combination

134

135

```scala { .api }

136

extension [T](arr: IArray[T]):

137

def ++[U >: T: ClassTag](suffix: IArray[U]): IArray[U]

138

def ++[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U]

139

def :+[U >: T: ClassTag](x: U): IArray[U]

140

def +:+[U >: T: ClassTag](suffix: IArray[U]): IArray[U]

141

def appended[U >: T: ClassTag](x: U): IArray[U]

142

def appendedAll[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U]

143

def prepended[U >: T: ClassTag](x: U): IArray[U]

144

def prependedAll[U >: T: ClassTag](prefix: IterableOnce[U]): IArray[U]

145

def concat[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U]

146

```

147

148

Operations for combining arrays and adding elements.

149

150

### Set-like Operations

151

152

```scala { .api }

153

extension [T](arr: IArray[T]):

154

def diff[U >: T](that: IArray[U]): IArray[T]

155

def diff[U >: T](that: Seq[U]): IArray[T]

156

def intersect[U >: T](that: IArray[U]): IArray[T]

157

def intersect[U >: T](that: Seq[U]): IArray[T]

158

def distinct: IArray[T]

159

def distinctBy[U](f: T => U): IArray[T]

160

```

161

162

## Sorting and Ordering

163

164

```scala { .api }

165

extension [T](arr: IArray[T]):

166

def sorted(using math.Ordering[T]): IArray[T]

167

def sortBy[U](f: T => U)(using math.Ordering[U]): IArray[T]

168

def sortWith(f: (T, T) => Boolean): IArray[T]

169

def reverse: IArray[T]

170

```

171

172

Sorting operations that return new sorted arrays.

173

174

## Conversion Operations

175

176

### Collection Conversions

177

178

```scala { .api }

179

extension [T](arr: IArray[T]):

180

def iterator: Iterator[T]

181

def reverseIterator: Iterator[T]

182

def toSeq: Seq[T]

183

def toList: List[T]

184

def toVector: Vector[T]

185

def toSet: Set[T]

186

```

187

188

Convert to other collection types.

189

190

### Array Conversions

191

192

```scala { .api }

193

extension [T](arr: IArray[T]):

194

@deprecated("Use IArray.genericWrapArray(myIArray).toArray instead")

195

def toArray: Array[T]

196

```

197

198

### Implicit Conversions to ArraySeq

199

200

```scala { .api }

201

implicit def genericWrapArray[T](arr: IArray[T]): ArraySeq[T]

202

implicit def wrapRefArray[T <: AnyRef](arr: IArray[T]): ArraySeq.ofRef[T]

203

implicit def wrapIntArray(arr: IArray[Int]): ArraySeq.ofInt

204

implicit def wrapDoubleIArray(arr: IArray[Double]): ArraySeq.ofDouble

205

implicit def wrapLongIArray(arr: IArray[Long]): ArraySeq.ofLong

206

implicit def wrapFloatIArray(arr: IArray[Float]): ArraySeq.ofFloat

207

implicit def wrapCharIArray(arr: IArray[Char]): ArraySeq.ofChar

208

implicit def wrapByteIArray(arr: IArray[Byte]): ArraySeq.ofByte

209

implicit def wrapShortIArray(arr: IArray[Short]): ArraySeq.ofShort

210

implicit def wrapBooleanIArray(arr: IArray[Boolean]): ArraySeq.ofBoolean

211

implicit def wrapUnitIArray(arr: IArray[Unit]): ArraySeq.ofUnit

212

```

213

214

## Factory Methods

215

216

### Basic Construction

217

218

```scala { .api }

219

object IArray:

220

def empty[T: ClassTag]: IArray[T]

221

def apply[T: ClassTag](xs: T*): IArray[T]

222

def apply(x: Boolean, xs: Boolean*): IArray[Boolean]

223

def apply(x: Byte, xs: Byte*): IArray[Byte]

224

def apply(x: Short, xs: Short*): IArray[Short]

225

def apply(x: Char, xs: Char*): IArray[Char]

226

def apply(x: Int, xs: Int*): IArray[Int]

227

def apply(x: Long, xs: Long*): IArray[Long]

228

def apply(x: Float, xs: Float*): IArray[Float]

229

def apply(x: Double, xs: Double*): IArray[Double]

230

def apply(x: Unit, xs: Unit*): IArray[Unit]

231

```

232

233

### Generation Methods

234

235

```scala { .api }

236

def from[A: ClassTag](it: IterableOnce[A]): IArray[A]

237

def fill[T: ClassTag](n: Int)(elem: => T): IArray[T]

238

def fill[T: ClassTag](n1: Int, n2: Int)(elem: => T): IArray[IArray[T]]

239

def tabulate[T: ClassTag](n: Int)(f: Int => T): IArray[T]

240

def tabulate[T: ClassTag](n1: Int, n2: Int)(f: (Int, Int) => T): IArray[IArray[T]]

241

def range(start: Int, end: Int): IArray[Int]

242

def range(start: Int, end: Int, step: Int): IArray[Int]

243

def iterate[T: ClassTag](start: T, len: Int)(f: T => T): IArray[T]

244

def concat[T: ClassTag](xss: IArray[T]*): IArray[T]

245

```

246

247

### Unsafe Construction

248

249

```scala { .api }

250

def unsafeFromArray[T](s: Array[T]): IArray[T]

251

```

252

253

Convert an array to immutable array without copying. The original array must not be mutated after this call.

254

255

## Usage Examples

256

257

### Basic Operations

258

259

```scala

260

import scala.*

261

262

// Creating arrays

263

val empty = IArray.empty[Int]

264

val numbers = IArray(1, 2, 3, 4, 5)

265

val fromRange = IArray.range(1, 10)

266

val filled = IArray.fill(5)("hello")

267

268

// Element access

269

val first = numbers.head // 1

270

val last = numbers.last // 5

271

val third = numbers(2) // 3

272

val maybeFirst = numbers.headOption // Some(1)

273

274

// Basic properties

275

val size = numbers.length // 5

276

val isEmpty = numbers.isEmpty // false

277

val indices = numbers.indices // Range(0, 1, 2, 3, 4)

278

```

279

280

### Transformations

281

282

```scala

283

val numbers = IArray(1, 2, 3, 4, 5)

284

285

// Mapping

286

val doubled = numbers.map(_ * 2) // IArray(2, 4, 6, 8, 10)

287

val strings = numbers.map(_.toString) // IArray("1", "2", "3", "4", "5")

288

289

// Filtering

290

val evens = numbers.filter(_ % 2 == 0) // IArray(2, 4)

291

val odds = numbers.filterNot(_ % 2 == 0) // IArray(1, 3, 5)

292

293

// Flat mapping

294

val expanded = numbers.flatMap(n => IArray.fill(n)(n))

295

// IArray(1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5)

296

297

// Collecting with partial functions

298

val evenDoubled = numbers.collect { case n if n % 2 == 0 => n * 2 }

299

// IArray(4, 8)

300

```

301

302

### Slicing and Selection

303

304

```scala

305

val data = IArray("a", "b", "c", "d", "e")

306

307

// Taking and dropping

308

val firstThree = data.take(3) // IArray("a", "b", "c")

309

val lastTwo = data.takeRight(2) // IArray("d", "e")

310

val skipFirst = data.drop(1) // IArray("b", "c", "d", "e")

311

val skipFirstTwo = data.drop(2) // IArray("c", "d", "e")

312

313

// Conditional taking/dropping

314

val letters = IArray("a", "b", "c", "1", "2")

315

val onlyLetters = letters.takeWhile(_.forall(_.isLetter)) // IArray("a", "b", "c")

316

317

// Slicing

318

val middle = data.slice(1, 4) // IArray("b", "c", "d")

319

val (left, right) = data.splitAt(2) // (IArray("a", "b"), IArray("c", "d", "e"))

320

```

321

322

### Search and Query

323

324

```scala

325

val values = IArray(10, 20, 30, 20, 40)

326

327

// Finding elements

328

val contains20 = values.contains(20) // true

329

val firstIndex = values.indexOf(20) // 1

330

val lastIndex = values.lastIndexOf(20) // 3

331

val indexOver25 = values.indexWhere(_ > 25) // 2

332

333

// Predicate testing

334

val hasLarge = values.exists(_ > 35) // true

335

val allPositive = values.forall(_ > 0) // true

336

val firstLarge = values.find(_ > 25) // Some(30)

337

val countLarge = values.count(_ > 25) // 2

338

```

339

340

### Combining Arrays

341

342

```scala

343

val arr1 = IArray(1, 2, 3)

344

val arr2 = IArray(4, 5, 6)

345

val list = List(7, 8, 9)

346

347

// Concatenation

348

val combined = arr1 ++ arr2 // IArray(1, 2, 3, 4, 5, 6)

349

val withList = arr1 ++ list // IArray(1, 2, 3, 7, 8, 9)

350

351

// Adding single elements

352

val withZero = 0 +: arr1 // IArray(0, 1, 2, 3)

353

val withTen = arr1 :+ 10 // IArray(1, 2, 3, 10)

354

355

// Prepending/appending collections

356

val prefixed = IArray(-2, -1) ++: arr1 // IArray(-2, -1, 1, 2, 3)

357

val suffixed = arr1 :++ IArray(10, 11) // IArray(1, 2, 3, 10, 11)

358

```

359

360

### Sorting and Ordering

361

362

```scala

363

val unsorted = IArray(3, 1, 4, 1, 5, 9, 2)

364

365

// Natural ordering

366

val sorted = unsorted.sorted // IArray(1, 1, 2, 3, 4, 5, 9)

367

368

// Custom ordering

369

val descending = unsorted.sortWith(_ > _) // IArray(9, 5, 4, 3, 2, 1, 1)

370

371

// Sort by transformation

372

val words = IArray("hello", "hi", "world", "a")

373

val byLength = words.sortBy(_.length) // IArray("a", "hi", "hello", "world")

374

375

// Reverse

376

val reversed = sorted.reverse // IArray(9, 5, 4, 3, 2, 1, 1)

377

```

378

379

### Advanced Operations

380

381

```scala

382

val data = IArray(1, 2, 3, 4, 5)

383

384

// Scanning (cumulative operations)

385

val cumSum = data.scanLeft(0)(_ + _) // IArray(0, 1, 3, 6, 10, 15)

386

val cumProduct = data.scanLeft(1)(_ * _) // IArray(1, 1, 2, 6, 24, 120)

387

388

// Folding (reduction to single value)

389

val sum = data.foldLeft(0)(_ + _) // 15

390

val product = data.foldRight(1)(_ * _) // 120

391

392

// Grouping and partitioning

393

val mixed = IArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

394

val (evens, odds) = mixed.partition(_ % 2 == 0)

395

// evens: IArray(2, 4, 6, 8, 10), odds: IArray(1, 3, 5, 7, 9)

396

397

// Set operations

398

val set1 = IArray(1, 2, 3, 4)

399

val set2 = IArray(3, 4, 5, 6)

400

val intersection = set1.intersect(set2) // IArray(3, 4)

401

val difference = set1.diff(set2) // IArray(1, 2)

402

val unique = IArray(1, 2, 2, 3, 3, 3).distinct // IArray(1, 2, 3)

403

```

404

405

### Conversion and Iteration

406

407

```scala

408

val arr = IArray("a", "b", "c", "d")

409

410

// To other collections

411

val list = arr.toList // List("a", "b", "c", "d")

412

val vector = arr.toVector // Vector("a", "b", "c", "d")

413

val set = arr.toSet // Set("a", "b", "c", "d")

414

415

// Iteration

416

arr.foreach(println) // Prints each element

417

val iterator = arr.iterator // Iterator for traversal

418

val reverseIter = arr.reverseIterator // Reverse iterator

419

420

// Side effects

421

arr.foreach(x => println(s"Element: $x"))

422

```

423

424

### Unsafe Operations and Performance

425

426

```scala

427

// Unsafe conversion from mutable array (use with caution)

428

val mutableArray = Array(1, 2, 3, 4, 5)

429

val immutableArray = IArray.unsafeFromArray(mutableArray)

430

// Warning: Do not modify mutableArray after this point!

431

432

// Efficient conversion through ArraySeq

433

val properConversion = IArray.genericWrapArray(immutableArray).toArray

434

```

435

436

IArray provides a complete immutable array implementation with excellent performance characteristics and a rich API that integrates seamlessly with Scala's collection library while maintaining type safety and immutability guarantees.