Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

maps - map manipulation

Enable with use maps;. Namespaced under maps.; every function is called as maps.NAME(...). Each function returns a new map (or list) - the input is never mutated:

use io;
use maps;

def scores as map of string to int init {"alice": 90, "bob": 80};
def names as list of string init maps.keys($scores);   # ["alice", "bob"]
def values as list of int init maps.values($scores);   # [90, 80]
def shrunk as map of string to int init maps.delete($scores, "bob");
def with_dave as map of string to int init maps.merge($scores, {"dave": 75});

Functions

CallReturnsNotes
maps.keys(m)list of <key type>The map’s keys, in insertion order.
maps.values(m)list of <value type>The map’s values, in insertion order.
maps.has(m, key)boolKey membership test. The non-erroring companion to $m[key].
maps.delete(m, key)mapNew map without key. Missing key is an error - see below.
maps.merge(a, b)mapNew map: a’s entries with b’s layered on top (b wins on collision).

maps.has

Reports whether the map contains the given key. Pair it with the indexed-read to avoid the missing-key runtime error:

def m as map of string to int init {"a": 1};
if (maps.has($m, "a")) {
    io.printf("%d\n", $m["a"]);   # safe - we just checked
}

This lived in core as bare has(...); it moved here because map-only membership is domain-specific and didn’t fit core’s “universally needed structural primitives” charter (len, by contrast, is genuinely polymorphic across string / list / map and stays). The lists side of “does this contain that?” is lists.contains, which checks values rather than keys - the differing names keep the role distinction visible at every call site.

maps.delete is strict

Deleting a key that isn’t in the map raises a positioned runtime error - matching the read-side rule that $m[missing] is an error rather than a silent default. Callers who want a “delete if present” shape can guard with maps.has:

if (maps.has($m, "stale")) {
    $m = maps.delete($m, "stale");
}

This is “strict at boundaries” applied to writes: silent no-ops on missing keys would let typos drift through unnoticed.

maps.merge ordering

merge(a, b) returns a’s entries in a’s insertion order, with b’s values overwriting where keys collide. New keys from b are appended in b’s insertion order. So merging {"x": 1, "y": 2} with {"y": 99, "z": 3} yields {"x": 1, "y": 99, "z": 3} - same shape Python’s {**a, **b} produces.

Value semantics

The library never modifies its inputs. maps.delete and maps.merge both copy, so the source maps stay intact for further use; the new map is independent of either.

See also: lists.md, index.md. len(m) is a language built-in (no import needed).