Reference / Arrays
Arrays
An array [T] holds values of the type T in order. Each value is an element, and its index tells its position, from 0.
fn main() {
let mut scores = [70, 85, 90]
scores[0] = 75
print(scores[0]) // 75
print(scores.len()) // 3
print(scores.sum()) // 250
}
An array is a value. When the program binds, passes or stores an array, it behaves as a copy (Arrays are values).
Array literals
An array literal [a, b, c] makes an array of its elements, in order. The program calculates the elements from left to right.
fn main() {
let names = ["Aino", "Eero"]
let rows = [[1, 2], [3]]
let found = [4, None, 6]
let empty: [i64] = []
print(names.len() + rows.len() + found.len() + empty.len()) // 7
}
The rules:
- All the elements have one type (E0032). The other elements decide the type of an integer literal, so
[1, 2.5]is an[f64](Literals). - A
Noneelement makes the type of the other elements optional. So[4, None, 6]is an[i64?]. []alone does not tell its type (E0050). Where the context expects an array, such as aletwith a type, a parameter or a field,[]gets that type.- An array literal can continue over many lines. A
,after the last element is valid.
Filled arrays
[value; length] makes an array of length elements. Each element is a copy of value.
fn main() {
let zeros = [0; 4]
let mut grid = [[0; 3]; 2]
grid[0][1] = 5
print(zeros.len()) // 4
print(grid[0][1]) // 5
print(grid[1][1]) // 0
}
The rules:
- The program calculates
valueonce, thenlength. lengthis ani64(E0032). A length of 0 gives an empty array.- At run time, a negative length stops the program with a panic. The program also panics when the size of the array in bytes is more than an
i64can hold. - When the type of
valueis a class or an optional class, every element would be the same object. This is an error (E0067), even when a binding of an optional class type holdsNone. A value whose type is a type parameter, such asT, is also an error, becauseTcan be a class (Generics). The literalNoneis the one exception:[None; length]is valid where the context gives its type, such aslet slots: [Box?] = [None; 3]. Without that context it is an error (E0050). - When
valueholds objects, such as an array of objects, every element holds the same objects.
fn main() {
let n = -1
let xs = [0; n]
print(xs.len())
}
sisu: panic at example.sisu:3:18: array length is negative
Indexes
xs[i] is the element at the index i (Indexes). The index is an i64. An index that is negative, or not less than the length, stops the program with a panic.
An assignment xs[i] = value replaces an element. The array must be in a place that can change, such as a let mut binding or a mut field (Assignment).
fn main() {
let mut grid = [[1, 2], [3, 4]]
grid[1][0] = 30
grid[0] = [10, 20, 25]
grid[0][2] += 5
print(grid[0][2] + grid[1][0]) // 60
}
The rules:
- A binding without
mutcannot change its array, also not an element of an inner array (E0001). - An object in an array stays shared, so its
mutfields can change also when the array cannot (Classes). - An optional array has no index. Unwrap it first, for example with
if let(E0062).
fn main() {
let grid = [[1, 2], [3, 4]]
grid[0][0] = 9 // error[E0001]
}
E0001: what this error means
for
A for loop runs its body once for each element of an array, in order.
fn main() {
let names = ["Aino", "Eero"]
for name in names {
print("Hello, {name}")
}
}
Hello, Aino Hello, Eero
print cannot take an array (E0060), and an interpolation cannot either (E0098). To print an array, print its elements in a for loop. The section Text of other types is in development, and it changes this rule.
Methods
An array has these methods:
| Method | Result | Meaning |
|---|---|---|
xs.len() |
i64 |
The number of elements |
xs.sum() |
The element type | The sum of the elements of an [i64] or an [f64] |
xs.contains(x) |
bool |
true when an element is equal to x, as == tells |
fn main() {
let xs = [3, 1, 4]
let weights = [0.5, 0.25]
let maybe = [1, None]
print(xs.len()) // 3
print(xs.sum()) // 8
print(weights.sum()) // 0.75
print(xs.contains(4)) // true
print(maybe.contains(None)) // true
}
The rules:
lenis a method, so writexs.len().xs.lenis an error (E0057), and so islen(xs)(E0070).sumtakes only an[i64]or an[f64](E0069). It adds the elements in order, and the sum of an empty array is zero.- On an
[i64], a sum outside the range ofi64stops the program with a panic (Overflow). - The argument of
containshas the element type (E0032). SoNoneis valid only when the elements are optional. containsuses==, socontains(f64.nan)is alwaysfalse(Types).- A name that is not one of these methods is an error (E0063).
- On an optional array, call a method with
?.(Optional chaining).
fn main() {
let flags = [true, false]
print(flags.sum()) // error[E0069]
}
E0069: what this error means
More methods In development
xs.push(x) adds x after the last element of xs. It writes the array, as xs[i] = x does. An array also has the iterator methods.
fn main() {
let mut xs = [1, 2]
xs.push(3)
print(xs.len()) // 3
print(xs.map(x => x * 2).sum()) // 12
}
Equality
Two arrays are equal when they have the same length and their elements are equal, in order (Equality). < and the other comparisons do not apply to arrays (E0032). Nor does is, because an array is not an object (E0046).
fn main() {
let a = [1, 2]
print(a == [1, 2]) // true
print(a == [2, 1]) // false
print(a != []) // true
}
Arrays are values
When the program binds an array, passes it or stores it, the array behaves as a copy. A change to one holder does not change the other holders (Values and memory).
fn main() {
let a = [1, 2, 3]
let mut b = a
b[0] = 10
print(a[0]) // 1
print(b[0]) // 10
}
The rules:
- An array that the program reads out of another array, or out of a field, is a value too. A write to it does not change the original.
- A copy of an array holds the same objects as the original. A change to a
mutfield of such an object shows in both arrays. - A function cannot change an array that it gets as an argument. A function that makes a changed array returns it, and the caller writes
xs = change(xs).
fn doubled(xs: [i64]) -> [i64] {
let mut out = xs
for i in 0..out.len() {
out[i] *= 2
}
return out
}
fn main() {
let mut xs = [1, 2, 3]
let before = xs
xs = doubled(xs)
print(xs[2]) // 6
print(before[2]) // 3
}
Sisu does not copy the elements when the program binds, passes or stores an array. The holders share the elements until a write to one of them. That write copies the elements first, and a loop that writes the array can copy them before it starts. A program cannot see when the copy occurs.
Sisu