Arrays
Array[T] is the standard immutable ordered collection. MutArray[T] is its
mutable counterpart. The representations are language-defined, while the
source names, methods, iteration provider, safe indexing protocol, equality,
and debugging support come from the standard library.
Array literals and inference
Section titled “Array literals and inference”func main() -> Unit do values = [1, 2, 3]; empty : Array[Int] = []; Debug.trace(values); Debug.trace(empty);endEvery element of a nonempty literal must have one common type. An empty literal
does not determine its element type, so it needs an annotation or another
nearby expected Array[T] type.
Array values are immutable: reading or passing an Array[T] never grants the
ability to replace an element.
Length and traversal
Section titled “Length and traversal”length() returns an Int. Use foreach when the element index has no
meaning:
func print_all(values : Array[String]) -> Unit do foreach value in values do Console.println(value); end;endThe standard array iterable visits elements in increasing index order.
Pure transformations
Section titled “Pure transformations”map returns a new array, applying its function from left to right.
reversed returns a new array and leaves its receiver unchanged:
func main() -> Unit do values = [1, 2, 3]; doubled = values.map(|value| value * 2); reversed = values.reversed(); Debug.trace(doubled); Debug.trace(reversed); Debug.trace(values);endmap is generic in its result element type, so a transformation may change
Array[T] into Array[U].
Checked indexing
Section titled “Checked indexing”Checked access uses values[index]!. It returns the element when the index is
valid and propagates IndexError::OutOfBounds otherwise:
func item_at(values : Array[Int], index : Int) throws IndexError -> Int do values[index]!end
test "checked indexing" do Testing.assert_equal(item_at([10, 20], 1)!, 20)!;endThe receiver and index are evaluated once. The shared IndexError carries the
requested index and current length.
unsafe_get(index) skips the check. Use it only when a nearby invariant proves
the index is valid and the function intentionally remains infallible. “The
caller should pass a valid index” is not a sufficient local invariant.
Mutable arrays
Section titled “Mutable arrays”Convert an immutable array with to_mut() when elements must be appended or
replaced:
func update_first(values : MutArray[Int]) throws IndexError -> Unit do values[0]! := 40;end
test "mutable array snapshots" do original = [1, 2]; mutable = original.to_mut(); mutable.push(3); update_first(mutable)!; snapshot = mutable.to_immut();
Testing.assert_equal(original, [1, 2])!; Testing.assert_equal(snapshot, [40, 2, 3])!;endto_mut() creates a distinct mutable copy; changing it cannot affect the
original. Two bindings of the same MutArray alias the same mutable storage.
to_immut() creates a snapshot, and later mutations cannot change that
snapshot.
push appends one element. pop removes and returns the final element as
Option[T]. Checked assignment uses mutable[index]! := value; and propagates
IndexError on failure. unsafe_set has the same strict in-bounds
precondition as unsafe_get.
MutArray is not directly iterable. If a traversal should see the elements
present at one moment, iterate over mutable.to_immut() and accept the snapshot
cost. Keep indexed mutation when mutable identity is part of the algorithm.
Next: Option and Result.