W# 0.1.1

Arrays and lists

std/array on fixed-length arrays, std/list on the growable one.

std/array

const array = @import("std/array");

[]T is fixed-length. Its count lives in the object header and there is no capacity beside it, so every one of these returns a new array.

len(a) i64
new(n) []Tn elements, zeroed; the element type comes from the context
concat(a, b) []T
push(a, v) []Ta new array one longer
slice(a, from, to) []Thalf-open
repeat(a, n) []T

array.push in a loop allocates a whole new array every call. Use std/list for that.

array.new(32) needs the context to say what the elements are. var b = array.new(32); on its own fails with cannot tell what type main is being used at, which is a known rough edge.

std/list

const list = @import("std/list");

List[T] is the second object that length needs: a backing array whose header length is the capacity, and a count of how much of it is in use. Pushing writes into the spare tail, only a full list reallocates, and it doubles when it does, so a run of pushes is amortised constant time.

new() List[T], with_capacity(n) List[T], from(a) List[T]
len(l) i64, capacity(l) i64
get(l, i) T, set(l, i, v) void
push(l, v) void, pop(l) T
insert(l, i, v) void, remove(l, i) T
extend(l, a) void, clear(l) void
to_array(l) []T
iter(l), next(it)what for calls
var steps: list.List[i64] = list.new();
list.push(steps, 7);
for (steps) |v, i| { }
print_int(list.len(steps));

pop and remove hand a value back and panic on an empty list rather than returning ?T, for the same reason a[i] panics: asking for element zero of an empty list is a bug, not a case.

for over anything

for over an array walks it by index. Over anything else it calls iter and next from the module that declares its type. That is how std/list is iterable without the type checker knowing what a list is, and it is how a container you write becomes iterable too: write those two functions.

next returns ?T, which is why a manual loop is while (list.next(it)) |v| { }.

Why these are W#

Both modules move references from one object into another: an array concat copies elements, and a list growth copies them into a new backing array. Anything that does that is written in W#, where the write barrier, the load barrier and the stack maps apply by construction. A builtin may read and write bytes, and that is the line.

Last changed 8 September 2026. Improve this page

On this page