Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: Standard library

Standard library

Maps

A map holds values by key, like a Map in TypeScript, except that it never changes. Each operation is called as map.<name>, and each one that changes a map gives you a new one.

Operation Gives Fails SQL form
count(entries) Int, at least 0 (SELECT count(*) FROM jsonb_object_keys(x))
get(entries, key) V? none
has(entries, key) Bool none
keys(entries) Set<K> none
values(entries) List<V>, in the canonical order of their keys none
with(entries, key, value) Map<K, V> with key set to value, added or replaced none
without(entries, key) Map<K, V> without key none
merge(first, second) Map<K, V> with both; second wins where both have a key none
filter(entries, (key, value) -> ...) Map<K, V>, the entries accepted none
map_values(entries, (key, value) -> ...) Map<K, U>, each key with the value given for it none
  • Walk a map through its keys: for key in map.keys(prices) goes through them in the canonical order. for over the map itself is type.mismatch, and its edit writes map.keys(<the map>).
  • An empty map is [] written where a map is expected, just as a list literal written where a set is expected is a set (Collections). A named map type's min_length checks that literal's length (type.invalid_literal). Add entries with map.with. There is no map literal with entries, so a list with items in it, where a map is expected, is type.mismatch.
  • Named types. As for lists, an operation that gives V?, Set<K> or List<V> keeps the named type of the keys or values. It doesn't keep a named map type, because without can break that type's min_length.
  • Records have no dynamic keys. There is no record[name]: a record's fields are fixed, and each has its own type, such as Customer.email. Keys known only while the program runs are what a Map is for.

A shop's stock, through every map operation. filter and map_values give their inline function each entry's key and value, in the canonical order of the keys:

example
type Loaf = Text {    min_length: 1    max_length: 40}type Stock = Int {    min: 0}/// The stock after `count` more of `loaf` arrive.function delivered(stock: Map<Loaf, Stock>, loaf: Loaf, count: Stock) -> Map<Loaf, Stock> {    var on_hand: Stock = match map.get(stock, loaf) {        some(found) -> found        none -> 0    }    return map.with(stock, loaf, Stock(on_hand + count))}/// The loaves with none left, in the canonical order of their names: a/// map is walked through its keys.function sold_out(stock: Map<Loaf, Stock>) -> List<Loaf> {    var mut out: List<Loaf> = []    for loaf in map.keys(stock) {        if (map.get(stock, loaf) == 0) {            out = list.append(out, loaf)        }    }    return out}/// How many loaves are on the shelves altogether.function on_shelves(stock: Map<Loaf, Stock>) -> Stock {    return Stock(list.sum(map.values(stock)))}/// The loaves to put out: any with some left, but never `withdrawn`.function on_show(stock: Map<Loaf, Stock>, withdrawn: Loaf) -> Map<Loaf, Stock> {    return map.filter(stock, (loaf, count) -> count > 0 and loaf != withdrawn)}/// Each loaf's stock once a tray of `per_tray` more arrives for it.function restocked(stock: Map<Loaf, Stock>, per_tray: Stock) -> Map<Loaf, Stock> {    return map.map_values(stock, (loaf, count) -> Stock(count + per_tray))}
example
test "map operations give new maps" {    var no_stock: Map<Loaf, Stock> = []    var stock: Map<Loaf, Stock> = map.with(map.with(no_stock, "Rye", 4), "Bap", 0)    assert map.count(no_stock) == 0    assert map.count(stock) == 2    assert map.get(stock, "Rye") == 4    assert map.get(stock, "Spelt") == none    assert map.has(stock, "Bap")    assert not map.has(stock, "Spelt")    assert map.keys(stock) == ["Bap", "Rye"]    assert map.values(stock) == [0, 4]  // in the canonical order of their keys    assert map.with(stock, "Rye", 6) == map.with(map.with(no_stock, "Bap", 0), "Rye", 6)    assert map.without(stock, "Bap") == map.with(no_stock, "Rye", 4)    assert map.without(stock, "Spelt") == stock    var fresh: Map<Loaf, Stock> = map.with(no_stock, "Rye", 9)    assert map.merge(stock, fresh) == map.with(map.with(no_stock, "Bap", 0), "Rye", 9)    assert delivered(stock, "Bap", 12) == map.with(stock, "Bap", 12)    assert delivered(stock, "Spelt", 3) == map.with(stock, "Spelt", 3)    assert sold_out(stock) == ["Bap"]    assert on_shelves(stock) == 4    var three: Map<Loaf, Stock> = map.with(stock, "Spelt", 2)    assert on_show(three, "Spelt") == map.with(no_stock, "Rye", 4)    assert restocked(stock, 6) == map.with(map.with(no_stock, "Bap", 6), "Rye", 10)}

map.get gives V?, so a key that may be missing is handled where it is read; map.has says whether it is there without reading it.

Markdown for agents: /docs/maps.md.Built from Jadpo main at a707efb.