Skip to content

Collections

Frank edited this page Jan 26, 2026 · 11 revisions

Collections (list / map / set)

Table of Contents

Lists

Create

let xs = list();
let ys = [];           // empty list literal
let zs = [1, 2, 3];    // list literal with elements

Spread

Use ... to expand a list literal:

let a = [1, 2, 3];
let b = [0, ...a, 4];  // [0, 1, 2, 3, 4]

Push / Pop

push(xs, 123);
let v = pop(xs);
  • push(list, value) appends
  • pop(list) returns last element or nil if empty

Length

len(xs)

Indexing

xs[0]
xs[i]

Rules:

  • index must be int
  • negative or out of range returns nil

Assigning by index

xs[2] = 999;

This can grow the list:

  • Missing intermediate elements become nil

Insert / Remove

insert(xs, index, value)  // insert at position
remove(xs, index)         // remove and return element at index

Slice

let sub = slice(xs, start, length);

Returns a new list with elements from start (inclusive) for length elements.

Extend

extend(xs, ys); // appends all elements of ys into xs

Index Of

let i = index_of(xs, 123); // returns index or -1

### Utilities

```c
list_unique(xs)   // remove duplicates (preserve order)
list_flatten(xs)  // flatten one level
list_chunk(xs, 2) // [[...], ...]
list_compact(xs)  // remove nils
list_sum(xs)      // sum numbers (nil ignored)

### Sort

```c
sort(xs); // in-place, default comparison (insertion)
sort(xs, "quick");
sort(xs, "merge");

fn desc(a, b) { return b - a; }
sort(xs, desc, "quick"); // custom comparator + algorithm

Maps

Maps accept any value as a key.

Key equality follows ==:

  • int and float compare by numeric value (so 1 equals 1.0)
  • string compares by content
  • Lists/maps/functions compare by identity (same object)

Create

let m = map();
let m2 = {};                          // empty map literal
let m3 = {"name": "Frank", "age": 30}; // map literal
let m4 = {1: "one", true: "yes", nil: "none"};

Spread

Use ... to expand a map literal (later keys override earlier keys):

let defaults = {theme: "dark", size: 12};
let config = {...defaults, size: 14};

Set / Get

Destructuring

Lists and maps can be destructured in let declarations:

let [a, b] = [1, 2];
let {x, y} = {"x": 10, "y": 20};
let {key: alias} = {"key": "value"};

Rest patterns capture remaining elements:

let [a, b, ...rest] = [1, 2, 3, 4];
let {x, ...other} = {x: 10, y: 20, z: 30};

Missing entries produce nil. Use _ to ignore a binding.

mset(m, "name", "Frank");
print(mget(m, "name"));

// non-string keys
mset(m, 42, "answer");
print(mget(m, 42));
  • Missing key returns nil

Has Key

mhas(m, "name") // bool
mhas(m, 42)      // bool

Keys

let ks = keys(m); // list of keys (any value)

Values

let vs = values(m); // list of values

Items (key-value pairs)

let pairs = items(m); // list of [key, value] lists

Map Iteration

Sets

Sets store unique values (based on ==).

Create

let s = set();
let s2 = set([1, 2, 2, 3]); // duplicates ignored
let s3 = set({a: 1, b: 2}); // keys from map

Add / Has / Del

set_add(s, 10);   // true if inserted
set_has(s, 10);   // true if present
set_del(s, 10);   // true if removed

Values

let xs = set_values(s); // list of values (order unspecified)

Iteration

for v in s {
  print(v);
}

Additional helpers for map iteration:

  • map_values(m) - Get all values as a list
let m = {"a": 1, "b": 2, "c": 3};
for v in map_values(m) {
  print("Value:", v);
}

Iteration Helpers

let xs = [1, 2, 3];
print(enumerate(xs)); // [[0,1], [1,2], [2,3]]

print(zip(["a", "b"], [10, 20, 30])); // [["a",10], ["b",20]]

fn is_even(x) { return x % 2 == 0; }
print(any(xs, is_even)); // true
print(all(xs, is_even)); // false

print(filter(xs, is_even)); // [2]
print(map(xs, fn(x) => x * 2)); // [2, 4, 6]

fn sum(a, b) { return a + b; }
print(reduce(xs, sum)); // 6

Data Quality-of-Life Functions

Copy and Deep Copy

  • copy(x) - Shallow copy of list or map
  • deepcopy(x) - Deep copy with cycle detection
let original = [1, 2, [3, 4]];
let shallow = copy(original);
let deep = deepcopy(original);

shallow[2][0] = 99;  // Affects original
deep[2][1] = 88;     // Does not affect original

Reverse

  • reverse(list) - In-place reversal
  • reversed(list) - Returns new reversed list
let list = [1, 2, 3, 4, 5];
reverse(list);  // list is now [5, 4, 3, 2, 1]

let rev = reversed([1, 2, 3]);  // Returns [3, 2, 1], original unchanged

Contains

  • contains(container, item) - Check if item exists

Works with lists, maps (checks keys), and strings:

print(contains([1, 2, 3], 2));           // true
print(contains({a: 1, b: 2}, "a"));      // true
print(contains("hello world", "world")); // true

Delete Key

mdel(m, "key"); // removes the key

Indexing with keys

m["name"]
m[42]

Field access on maps

If m is a map, m.name reads m["name"].

If m is not a map, field access is a runtime error.

Clone this wiki locally