09 · Data Structures
Arrays
Ordered collection with indexing, slicing, spread, and functional operations.
On this page
An array is Zolo's most basic collection: an ordered list of values accessible
by position (0-indexed). The type is inferred as [T] from the literal
[a, b, c].
Indexing and size are straightforward:
Literal, indexing, push/pop, slicing, spread, and functional operations.
// Feature: Arrays — 0-indexed ordered collection
// Syntax: `[a, b, c]`, indexing `arr[i]`, slicing `arr[i..j]`
// When to use: list of N values accessible by position, order
// matters, frequent append/pop.
use std::Array
// Literal and 0-based indexing.
let nums = [10, 20, 30, 40, 50]
print(nums[0]) // 10
print(nums[4]) // 50
print(nums.len()) // 5
// Type inferred as `[int]`. Explicit annotation:
let names: [str] = ["Alice", "Bob", "Carol"]
print(names[1]) // Bob
// Mutability: `let mut` + `Array.push/pop` or `.push()`.
let mut bag = [1, 2, 3]
bag.push(4)
bag.push(5)
print(bag) // [1, 2, 3, 4, 5]
let last = bag.pop()
print(last) // 5
print(bag) // [1, 2, 3, 4]
// Slicing by range — creates a new array.
let s = nums[0..3] // [10, 20, 30] exclusive
let t = nums[2..=4] // [30, 40, 50] inclusive
print(s)
print(t)
// Spread in literals.
let a = [1, 2]
let b = [3, 4]
let merged = [0, ...a, ...b, 5]
print(merged) // [0, 1, 2, 3, 4, 5]
// Functional operations (see also 05-functions/06-higher-order).
let doubled = Array::map([1, 2, 3], |x| x * 2)
let evens = Array::filter([1, 2, 3, 4], |x| x % 2 == 0)
let total = Array::reduce([1, 2, 3, 4], |acc, x| acc + x, 0)
print(doubled) // [2, 4, 6]
print(evens) // [2, 4]
print(total) // 10
// Sort and reverse — return a new array.
let desc = Array::sort([3, 1, 4, 1, 5, 9, 2]).reverse()
print(desc) // [9, 5, 4, 3, 2, 1, 1]
A few important points:
- Slicing with
[i..j](exclusive) or[i..=j](inclusive) creates a new array. - Spread
[...a, ...b]merges arrays inside a new literal. Array::mapandArray::filterreturn new arrays without modifying the original.Array::reducecombines the elements into one result.
Optional elements keep their position
An element of an array can be nil: [nil, 8, nil] has length 3.
Assigning nil to an existing position or calling push(nil) keeps that
position present. pop() and remove_at(index) remove positions.
Iteration visits each slot, including the first and last when they contain nil.
Preserve missing scores through construction, iteration and an iterator pipeline.
// Missing values still occupy array slots.
let scores: [int?] = [nil, 8, nil]
scores.push(nil)
print(scores.len()) // 4
for index, score in scores {
print("{index}: {score ?? 0}")
}
// Mapping to nil preserves the number and order of results.
let optional_scores = Iter.from(scores)
.map(|score| if (score ?? 0) == 8 { score } else { nil })
.collect()
print(optional_scores)
map preserves one result per input even when its callback returns nil.
Use filter to remove unwanted elements deliberately. Maps retain their
different key semantics: assigning nil removes a key.
Challenge
Use Array::filter to keep the odd numbers from [1, 2, 3, 4, 5, 6],
then use Array::reduce to sum the result. The sum should be 9.
See also