std.list

Reed's standard library. Imported with use std.list; not on disk.

Functions

int_listAn empty IntList with a small initial capacity.
int_list_with_capacityAn empty IntList sized to hold capacity elements without reallocating.
int_list_fromAn IntList holding a copy of values.
long_listAn empty LongList.
ref_listAn empty RefList.

int_list #

line 62
func int_list() -> &IntList

An empty IntList with a small initial capacity.

Returns
a new empty list
See also
int_list_with_capacity
Source
func int_list() -> &IntList {
  return new IntList { items: new I32Values[8]{}, count: 0 };
}

int_list_with_capacity #

line 74
func int_list_with_capacity(capacity: i32) -> &IntList

An empty IntList sized to hold capacity elements without reallocating.

Worth using when the eventual size is known: it turns a sequence of doubling copies into a single allocation. A capacity below 1 is raised to 1, since a zero-length backing array can never double.

Parameters
capacity — how many elements to reserve room for
Returns
a new empty list
Source
func int_list_with_capacity(capacity: i32) -> &IntList {
  return new IntList { items: new I32Values[capacity < 1 ? 1 : capacity]{}, count: 0 };
}

int_list_from #

line 82
func int_list_from(values: &I32Values) -> &IntList

An IntList holding a copy of values.

Parameters
values — the initial contents
Returns
a new list with those elements
Source
func int_list_from(values: &I32Values) -> &IntList {
  let items: &I32Values = new I32Values[#values < 1 ? 1 : #values]{};
  items.copy(0, values, 0, #values);
  return new IntList { items: items, count: #values };
}

long_list #

line 332
func long_list() -> &LongList

An empty LongList.

Returns
a new empty list
Source
func long_list() -> &LongList {
  return new LongList { items: new I64Values[8]{}, count: 0 };
}

ref_list #

line 409
func ref_list() -> &RefList

An empty RefList.

Returns
a new empty list
Source
func ref_list() -> &RefList {
  return new RefList { items: new AnyValues[8]{}, count: 0 };
}

Methods

IntList.lenHow many elements the list holds.
IntList.capacityHow many elements the list can hold before it must grow.
IntList.is_emptyWhether the list holds no elements.
IntList.reserveEnsures the list can hold at least capacity elements without reallocating.
IntList.pushAppends value to the end of the list, growing it if necessary.
IntList.popRemoves and returns the last element.
IntList.atThe element at index.
IntList.get_orThe element at index, or fallback when the index is out of range.
IntList.setOverwrites the element at index.
IntList.insertInserts value at index, shifting later elements right.
IntList.removeRemoves the element at index, shifting later elements left.
IntList.clearRemoves every element, keeping the allocated capacity.
IntList.index_ofThe index of the first element equal to value, or -1.
IntList.containsWhether the list holds an element equal to value.
IntList.sumThe sum of every element, wrapping on overflow like +.
IntList.minThe smallest element, or (0, 0) when the list is empty.
IntList.maxThe largest element, or (0, 0) when the list is empty.
IntList.reverseReverses the list in place.
IntList.extendAppends every element of other to self.
IntList.cloneAn independent copy of the list.
IntList.to_arrayThe list's elements as a plain array, sized exactly to the length.
LongList.lenHow many elements the list holds.
LongList.is_emptyWhether the list holds no elements.
LongList.pushAppends value, growing the list if necessary.
LongList.popRemoves and returns the last element, or (0, 0) when empty.
LongList.atThe element at index, trapping when out of range.
LongList.setOverwrites the element at index, ignoring an out-of-range index.
LongList.clearRemoves every element, keeping the allocated capacity.
LongList.sumThe sum of every element, wrapping on overflow.
RefList.lenHow many elements the list holds.
RefList.is_emptyWhether the list holds no elements.
RefList.pushAppends value, growing the list if necessary.
RefList.popRemoves and returns the last element, or (null, 0) when empty.
RefList.atThe element at index, or null when out of range.
RefList.setOverwrites the element at index, ignoring an out-of-range index.
RefList.clearRemoves every element, releasing the list's references to them.

IntList.len #

line 94
func IntList.len(self: &IntList) -> i32

How many elements the list holds.

Not the same as #list.items, which is the capacity.

Returns
the element count
See also
IntList.capacity
Source
func IntList.len(self: &IntList) -> i32 {
  return self->count;
}

IntList.capacity #

line 102
func IntList.capacity(self: &IntList) -> i32

How many elements the list can hold before it must grow.

Returns
the current capacity
See also
IntList.len
Source
func IntList.capacity(self: &IntList) -> i32 {
  return #self->items;
}

IntList.is_empty #

line 109
func IntList.is_empty(self: &IntList) -> i32

Whether the list holds no elements.

Returns
1 when empty, 0 otherwise
Source
func IntList.is_empty(self: &IntList) -> i32 {
  return self->count == 0;
}

IntList.reserve #

line 116
func IntList.reserve(self: &IntList, capacity: i32) -> void

Ensures the list can hold at least capacity elements without reallocating.

Parameters
capacity — the required capacity
Source
func IntList.reserve(self: &IntList, capacity: i32) {
  if (capacity <= #self->items) { return; }
  var next: i32 = #self->items;
  loop grow() {
    next = next * 2;
    if (next >= capacity) { break grow(); }
    continue grow();
  }
  let bigger: &I32Values = new I32Values[next]{};
  bigger.copy(0, self->items, 0, self->count);
  self->items = bigger;
}

IntList.push #

line 133
func IntList.push(self: &IntList, value: i32) -> void

Appends value to the end of the list, growing it if necessary.

Parameters
value — the element to append
See also
IntList.pop
Source
func IntList.push(self: &IntList, value: i32) {
  self.reserve(self->count + 1);
  self->items[self->count] = value;
  self->count = self->count + 1;
}

IntList.pop #

line 146
func IntList.pop(self: &IntList) -> (i32, i32)

Removes and returns the last element.

Returns (0, 0) for an empty list. The second result distinguishes "popped a zero" from "there was nothing to pop", which a bare sentinel cannot.

Returns
(value, ok) -- the removed element, and 1 when one was removed
See also
IntList.push
Source
func IntList.pop(self: &IntList) -> (i32, i32) {
  if (self->count == 0) { return (0, 0); }
  self->count = self->count - 1;
  return (self->items[self->count], 1);
}

IntList.at #

line 160
func IntList.at(self: &IntList, index: i32) -> i32

The element at index.

Traps when index is out of range, matching std.str's byte: a direct index that is out of range is a caller bug, not a value to paper over.

Parameters
index — which element
Returns
the element
See also
IntList.get_or
Source
func IntList.at(self: &IntList, index: i32) -> i32 {
  if (index < 0 || index >= self->count) { unreachable; }
  return self->items[index];
}

IntList.get_or #

line 171
func IntList.get_or(self: &IntList, index: i32, fallback: i32) -> i32

The element at index, or fallback when the index is out of range.

Parameters
index — which element
fallback — what to return when out of range
Returns
the element or fallback
See also
IntList.at
Source
func IntList.get_or(self: &IntList, index: i32, fallback: i32) -> i32 {
  if (index < 0 || index >= self->count) { return fallback; }
  return self->items[index];
}

IntList.set #

line 183
func IntList.set(self: &IntList, index: i32, value: i32) -> void

Overwrites the element at index.

Out-of-range indices are ignored rather than growing the list, since a write past the end has no obvious meaning (should the gap be zero-filled?).

Parameters
index — which element
value — the new value
Source
func IntList.set(self: &IntList, index: i32, value: i32) {
  if (index < 0 || index >= self->count) { return; }
  self->items[index] = value;
}

IntList.insert #

line 195
func IntList.insert(self: &IntList, index: i32, value: i32) -> void

Inserts value at index, shifting later elements right.

An index at or past the length appends; a negative one prepends.

Parameters
index — where to insert
value — the element to insert
See also
IntList.remove
Source
func IntList.insert(self: &IntList, index: i32, value: i32) {
  let at: i32 = index < 0 ? 0 : (index > self->count ? self->count : index);
  self.reserve(self->count + 1);
  // Copy backwards through the overlap: `array.copy` handles overlapping ranges correctly
  // (it is specified as if through an intermediate), so one call moves the whole tail.
  self->items.copy(at + 1, self->items, at, self->count - at);
  self->items[at] = value;
  self->count = self->count + 1;
}

IntList.remove #

line 212
func IntList.remove(self: &IntList, index: i32) -> (i32, i32)

Removes the element at index, shifting later elements left.

Returns (0, 0) when index is out of range.

Parameters
index — which element to remove
Returns
(value, ok) -- the removed element, and 1 when one was removed
See also
IntList.insert
Source
func IntList.remove(self: &IntList, index: i32) -> (i32, i32) {
  if (index < 0 || index >= self->count) { return (0, 0); }
  let removed: i32 = self->items[index];
  self->items.copy(index, self->items, index + 1, self->count - index - 1);
  self->count = self->count - 1;
  return (removed, 1);
}

IntList.clear #

line 223
func IntList.clear(self: &IntList) -> void

Removes every element, keeping the allocated capacity.

See also
IntList.len
Source
func IntList.clear(self: &IntList) {
  self->count = 0;
}

IntList.index_of #

line 232
func IntList.index_of(self: &IntList, value: i32) -> i32

The index of the first element equal to value, or -1.

Parameters
value — what to search for
Returns
the index, or -1 when absent
See also
IntList.contains
Source
func IntList.index_of(self: &IntList, value: i32) -> i32 {
  for i in 0..self->count {
    if (self->items[i] == value) { return i; }
  }
  return -1;
}

IntList.contains #

line 243
func IntList.contains(self: &IntList, value: i32) -> i32

Whether the list holds an element equal to value.

Parameters
value — what to search for
Returns
1 when present, 0 otherwise
Source
func IntList.contains(self: &IntList, value: i32) -> i32 {
  return self.index_of(value) >= 0;
}

IntList.sum #

line 250
func IntList.sum(self: &IntList) -> i32

The sum of every element, wrapping on overflow like +.

Returns
the sum
Source
func IntList.sum(self: &IntList) -> i32 {
  var total: i32 = 0;
  for i in 0..self->count {
    total = total + self->items[i];
  }
  return total;
}

IntList.min #

line 262
func IntList.min(self: &IntList) -> (i32, i32)

The smallest element, or (0, 0) when the list is empty.

Returns
(value, ok)
See also
IntList.max
Source
func IntList.min(self: &IntList) -> (i32, i32) {
  if (self->count == 0) { return (0, 0); }
  var best: i32 = self->items[0];
  for i in 1..self->count {
    if (self->items[i] < best) { best = self->items[i]; }
  }
  return (best, 1);
}

IntList.max #

line 275
func IntList.max(self: &IntList) -> (i32, i32)

The largest element, or (0, 0) when the list is empty.

Returns
(value, ok)
See also
IntList.min
Source
func IntList.max(self: &IntList) -> (i32, i32) {
  if (self->count == 0) { return (0, 0); }
  var best: i32 = self->items[0];
  for i in 1..self->count {
    if (self->items[i] > best) { best = self->items[i]; }
  }
  return (best, 1);
}

IntList.reverse #

line 285
func IntList.reverse(self: &IntList) -> void

Reverses the list in place.

Source
func IntList.reverse(self: &IntList) {
  var lo: i32 = 0;
  var hi: i32 = self->count - 1;
  loop swap() {
    if (lo >= hi) { break swap(); }
    let t: i32 = self->items[lo];
    self->items[lo] = self->items[hi];
    self->items[hi] = t;
    lo = lo + 1;
    hi = hi - 1;
    continue swap();
  }
}

IntList.extend #

line 302
func IntList.extend(self: &IntList, other: &IntList) -> void

Appends every element of other to self.

Parameters
other — the list to append
Source
func IntList.extend(self: &IntList, other: &IntList) {
  self.reserve(self->count + other->count);
  self->items.copy(self->count, other->items, 0, other->count);
  self->count = self->count + other->count;
}

IntList.clone #

line 311
func IntList.clone(self: &IntList) -> &IntList

An independent copy of the list.

Returns
a new list with the same elements
Source
func IntList.clone(self: &IntList) -> &IntList {
  let items: &I32Values = new I32Values[#self->items]{};
  items.copy(0, self->items, 0, self->count);
  return new IntList { items: items, count: self->count };
}

IntList.to_array #

line 323
func IntList.to_array(self: &IntList) -> &I32Values

The list's elements as a plain array, sized exactly to the length.

This is the bridge to std.sort and to any code that wants a bare array rather than a list; the array is a copy, so mutating it does not disturb the list.

Returns
a new array holding the elements
Source
func IntList.to_array(self: &IntList) -> &I32Values {
  let out: &I32Values = new I32Values[self->count]{};
  out.copy(0, self->items, 0, self->count);
  return out;
}

LongList.len #

line 339
func LongList.len(self: &LongList) -> i32

How many elements the list holds.

Returns
the element count
Source
func LongList.len(self: &LongList) -> i32 {
  return self->count;
}

LongList.is_empty #

line 346
func LongList.is_empty(self: &LongList) -> i32

Whether the list holds no elements.

Returns
1 when empty, 0 otherwise
Source
func LongList.is_empty(self: &LongList) -> i32 {
  return self->count == 0;
}

LongList.push #

line 353
func LongList.push(self: &LongList, value: i64) -> void

Appends value, growing the list if necessary.

Parameters
value — the element to append
Source
func LongList.push(self: &LongList, value: i64) {
  if (self->count == #self->items) {
    let bigger: &I64Values = new I64Values[#self->items * 2]{};
    bigger.copy(0, self->items, 0, self->count);
    self->items = bigger;
  }
  self->items[self->count] = value;
  self->count = self->count + 1;
}

LongList.pop #

line 366
func LongList.pop(self: &LongList) -> (i64, i32)

Removes and returns the last element, or (0, 0) when empty.

Returns
(value, ok)
Source
func LongList.pop(self: &LongList) -> (i64, i32) {
  if (self->count == 0) { return (0, 0); }
  self->count = self->count - 1;
  return (self->items[self->count], 1);
}

LongList.at #

line 376
func LongList.at(self: &LongList, index: i32) -> i64

The element at index, trapping when out of range.

Parameters
index — which element
Returns
the element
Source
func LongList.at(self: &LongList, index: i32) -> i64 {
  if (index < 0 || index >= self->count) { unreachable; }
  return self->items[index];
}

LongList.set #

line 385
func LongList.set(self: &LongList, index: i32, value: i64) -> void

Overwrites the element at index, ignoring an out-of-range index.

Parameters
index — which element
value — the new value
Source
func LongList.set(self: &LongList, index: i32, value: i64) {
  if (index < 0 || index >= self->count) { return; }
  self->items[index] = value;
}

LongList.clear #

line 391
func LongList.clear(self: &LongList) -> void

Removes every element, keeping the allocated capacity.

Source
func LongList.clear(self: &LongList) {
  self->count = 0;
}

LongList.sum #

line 398
func LongList.sum(self: &LongList) -> i64

The sum of every element, wrapping on overflow.

Returns
the sum
Source
func LongList.sum(self: &LongList) -> i64 {
  var total: i64 = 0;
  for i in 0..self->count {
    total = total + self->items[i];
  }
  return total;
}

RefList.len #

line 416
func RefList.len(self: &RefList) -> i32

How many elements the list holds.

Returns
the element count
Source
func RefList.len(self: &RefList) -> i32 {
  return self->count;
}

RefList.is_empty #

line 423
func RefList.is_empty(self: &RefList) -> i32

Whether the list holds no elements.

Returns
1 when empty, 0 otherwise
Source
func RefList.is_empty(self: &RefList) -> i32 {
  return self->count == 0;
}

RefList.push #

line 433
func RefList.push(self: &RefList, value: ?any) -> void

Appends value, growing the list if necessary.

value may be null: a RefList distinguishes "holds null at index 3" from "has no index 3", which is why at does not use null as its out-of-range answer.

Parameters
value — the element to append
Source
func RefList.push(self: &RefList, value: ?any) {
  if (self->count == #self->items) {
    let bigger: &AnyValues = new AnyValues[#self->items * 2]{};
    bigger.copy(0, self->items, 0, self->count);
    self->items = bigger;
  }
  self->items[self->count] = value;
  self->count = self->count + 1;
}

RefList.pop #

line 446
func RefList.pop(self: &RefList) -> (?any, i32)

Removes and returns the last element, or (null, 0) when empty.

Returns
(value, ok)
Source
func RefList.pop(self: &RefList) -> (?any, i32) {
  if (self->count == 0) { return (null, 0); }
  self->count = self->count - 1;
  let value: ?any = self->items[self->count];
  // Drop the list's own reference so a popped object can be collected while the list
  // lives on. Without this, a long-lived list pins every object it ever held.
  self->items[self->count] = null;
  return (value, 1);
}

RefList.at #

line 462
func RefList.at(self: &RefList, index: i32) -> ?any

The element at index, or null when out of range.

Narrow the result with is (spec section 9) to recover its type.

Parameters
index — which element
Returns
the element, or null
Source
func RefList.at(self: &RefList, index: i32) -> ?any {
  if (index < 0 || index >= self->count) { return null; }
  return self->items[index];
}

RefList.set #

line 471
func RefList.set(self: &RefList, index: i32, value: ?any) -> void

Overwrites the element at index, ignoring an out-of-range index.

Parameters
index — which element
value — the new value
Source
func RefList.set(self: &RefList, index: i32, value: ?any) {
  if (index < 0 || index >= self->count) { return; }
  self->items[index] = value;
}

RefList.clear #

line 480
func RefList.clear(self: &RefList) -> void

Removes every element, releasing the list's references to them.

Unlike IntList.clear, this nulls the vacated slots: leaving stale references would keep every object the list ever held alive for as long as the list itself.

Source
func RefList.clear(self: &RefList) {
  self->items.fill(0, null, self->count);
  self->count = 0;
}

Types

IntListA growable list of i32 values.
LongListA growable list of i64 values.
RefListA growable list of nullable references, for heterogeneous contents.

IntList #

line 38
struct IntList {
  items: mut &I32Values,
  count: mut i32,
}

A growable list of i32 values.

Source
struct IntList {
  items: mut &I32Values,
  count: mut i32,
}

LongList #

line 44
struct LongList {
  items: mut &I64Values,
  count: mut i32,
}

A growable list of i64 values.

Source
struct LongList {
  items: mut &I64Values,
  count: mut i32,
}

RefList #

line 53
struct RefList {
  items: mut &AnyValues,
  count: mut i32,
}

A growable list of nullable references, for heterogeneous contents.

Elements are ?any: a struct, an array, a string, a boxed i31, or null. Read one back with at and narrow it with is (spec section 9).

Source
struct RefList {
  items: mut &AnyValues,
  count: mut i32,
}