Skip to content

Lists

Store, transform, sort, and slice ordered growable values.

Updated View as Markdown

List[T], normally written []T, is an owned growable sequence.

mut names: []string = ["Ada", "Grace"]
names.add("Lin")

List.new[T](capacity) and List.with_capacity[T](capacity) create empty lists. The capacity argument reserves storage without changing the length. List.copy(other, capacity) creates an independent list and never chooses a capacity smaller than the source length.

mut queue := List.with_capacity[Job](64)
copy := List.copy(queue)

The empty list literal [] relies on context or later use to infer its element type. Add an annotation when there is no such context.

Access

first: string? = names.first()
third: string? = names.get(2)

get, first, and last are safe and optional. set overwrites an existing index on a mutable receiver; it is a no-op when the index is outside the current length and never extends the list. Use add to append.

Method Out-of-range behavior
get(index) None
first(), last() None for an empty list
set(index, value) No operation
get_unchecked(index) Caller must prove the index is valid

get_unchecked skips bounds checks and belongs only in low-level code with an explicit proof such as index < values.len().

Inspection methods include size, len, capacity, is_empty, and is_not_empty. size and len are aliases. reserve(additional) ensures room for that many more elements; it does not change the logical length.

Transformations

lengths := names.map(name => name.length())
long_names := names.filter(name => name.length() > 3)
total := lengths.fold(0, (sum, value) => sum + value)

Lists provide map, filter, flat_map, fold, reduce, scan, any, all, none, find, find_index, count, and enumerate.

fold and reduce both take an explicit initial accumulator. scan returns every running accumulator and includes the initial value as its first element. any, all, and none short-circuit once the answer is known.

Aggregate methods include sum, sum_of, average, min, max, and key-based min_by, max_by, min_of, and max_of. Empty min/max operations return None. Trait bounds make requirements explicit: numeric aggregates need Numeric, while extrema and sorting need Comparable.

Ordering

sorted, sorted_descending, sorted_by, and sorted_by_descending return new lists. reversed is an iterator, while shuffled returns a new list. The source list is not reordered in place.

by_name := users.sorted_by(user => user.name)
for user in users.reversed() {
    visit(user)
}

Windows

take, take_last, take_while, skip, skip_last, and skip_while produce owned lists. slice(range) returns Slice[T]?, a borrowed view:

middle := names.slice(1..3)

Ranges are half-open. slice returns None when start > end or the end lies past the list length. A Slice[T] borrows the parent storage and supports safe access, nested slicing, in-place replacement, and to_list() for an owned copy.

chunked(size) creates consecutive chunks. windowed(size, step) creates overlapping or strided windows. Keep size and step positive; invalid values are not a substitute for an empty-result policy.

Reshaping

Operation Result
group_by(key) Map[K, []T]
partition(predicate) (matching, non_matching)
associate(pair) Map from returned key/value tuples
associate_by(key) Map keyed by each element; later duplicates win
zip(other) Pairs up to the shorter list
flatten() Concatenates a list of lists
distinct, distinct_by Preserve the first occurrence

plus, plus_all, minus, and related methods return a new list. add, set, reserve, and clear mutate the receiver. Set-like intersect, union, subtract, and distinct require values with compatible equality and hashing.

join(separator) stringifies elements. join_of(separator, format) formats each element explicitly before joining.

Iteration

Lists implement Iterable[T]:

for name in names {
    println(name)
}

See Iteration for iterator adapters and Sequences for list/slice type syntax.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close