Arrays

Arrays are dynamic, homogeneous reference values. Append [] to an element type and initialize the variable with an array literal:

int[] values = [1, 2, 3]
str[] names = []
int[][] matrix = [[1, 2], [3, 4]]

An empty literal needs a type context, such as a variable declaration, function argument, or return value. A standalone empty literal is rejected because its element type cannot be inferred. A trailing comma is allowed.

Use len to read the current length, push to append, and brackets to read or replace an element:

values.push(5)
values[0] = 8
values[1] += 10
print(values.len(), values[0])

Each built-in that takes an array, a string, bytes, or a map first, and each function of the prelude, as map, filter, and sort, is also a method of it: values.push(5) is push(values, 5), and text.split(",").join(" ") is join(split(text, ","), " "). Both are written in this reference, and a type's own method of the same name, as one declared with func str[].push(self, ...), comes first.

pop(values) removes and returns the last element. Popping an empty array terminates the program with a runtime error. These built-ins work on arrays too:

Built-in Result Behavior
insert(a, index, value) none puts value at index, from 0 to len(a), moving later elements up
remove_at(a, index) element removes the element at index and returns it
reverse(a) none reverses the order of the elements in place
slice(a, start, end) array a new array with the elements from start up to end
view(a, start, end) array the elements from start up to end, shared with a rather than copied
reserve(a, count) none makes room for count more elements, so adding them does not grow the array again
push_bytes(a, data) none adds the values of bytes data to the end of a u8[]
find(a, value) i64 the index of the first element equal to value, or -1
a + b array a new array with the elements of a, then those of b

view makes an array of part of another without copying it: an element written through either is written in both, and a view keeps showing its array's elements after the array grows. Its length cannot change, so push, pop, insert, and remove_at on a view are runtime errors, and using a view whose array has become shorter than it is one too. Operations that work in place, such as sort and reverse, change just the view's elements:

int[] scores = [7, 3, 9, 1, 8]
sort(view(scores, 0, 3))          // scores is now [3, 7, 9, 1, 8]
int[] best = view(scores, 2, 5)
best[0] = 10                      // scores[2] is now 10

A view of a view shows the same array, and a view of a constant's array cannot change it either. slice gives an array of its own instead.

find and in work for the element types that maps accept as keys. Sorting, map, filter, and the other operations that take a function are described under functions as values.

Arrays remain shared when passed to or returned from functions, so push and indexed assignment inside a function affect the same array. Indexes must be integers. Negative and out-of-range indexes terminate the program with a Cuarzo runtime error instead of reading invalid memory.

The garbage collector reclaims an array once nothing refers to it, so there is no explicit deletion.