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

Sets

A set holds items of one type, each only once, and has no order your code can use. Each operation is called as set.<name>, and each one that changes a set gives you a new one.

Operation Gives Fails SQL form
count(items) Int, at least 0 jsonb_array_length(x)::bigint
contains(items, item) Bool none
with(items, item) Set<T> with item; the same set if already there none
without(items, item) Set<T> without item none
union(a, b) Set<T>, items in either none
intersection(a, b) Set<T>, items in both none
difference(a, b) Set<T>, items in a and not in b none
  • No loop needed. Each of these is one operation in the runtime, so you never walk a set with for to get its result.
  • Named types. As for lists, an operation that gives T or Set<T> keeps the items' named type. It doesn't keep a named set type, because without can break that type's min_length; build the result back into it by construction, as a named collection's lengths require (Named collection construction).
  • for walks a set in the canonical order of its values (Collections), the order everything that shows a set uses. The loop's variable takes the set's item type, as it does over a list. A set still has no index and no first item.
  • There is no filter, any, all or map on a set. Use for.

A bakery's labels, through every set operation and a for over a set:

example
type RecipeName = Text {    min_length: 1    max_length: 40}type Hazard = Enum {    gluten    milk    nuts    sesame}type Recipe = Object {    name: RecipeName    warnings: Set<Hazard>}type SafeToEat = Bool {}/// Whether `recipe` carries none of the warnings in `avoid`.function safe_for(recipe: Recipe, avoid: Set<Hazard>) -> SafeToEat {    return SafeToEat(set.count(set.intersection(recipe.warnings, avoid)) == 0)}/// Every warning a tray of recipes carries, each once.function tray_warnings(recipes: List<Recipe>) -> Set<Hazard> {    var mut found: Set<Hazard> = []    for recipe in recipes {        found = set.union(found, recipe.warnings)    }    return found}/// The warnings as a label prints them: a set is walked in its canonical/// order, which for an enum is the order its variants are declared in.function label(warnings: Set<Hazard>) -> List<Hazard> {    var mut shown: List<Hazard> = []    for hazard in warnings {        shown = list.append(shown, hazard)    }    return shown}
example
test "set operations give new sets" {    var loaf: Recipe = Recipe {        name: "Seeded loaf"        warnings: [Hazard.sesame, Hazard.gluten]    }    var flapjack: Recipe = Recipe {        name: "Flapjack"        warnings: [Hazard.milk]    }    assert set.count(loaf.warnings) == 2    assert set.contains(loaf.warnings, Hazard.sesame)    assert not set.contains(flapjack.warnings, Hazard.nuts)    assert set.with(loaf.warnings, Hazard.gluten) == loaf.warnings  // already there    assert set.with(flapjack.warnings, Hazard.nuts) == [Hazard.milk, Hazard.nuts]    assert set.without(loaf.warnings, Hazard.sesame) == [Hazard.gluten]    var in_either: Set<Hazard> = set.union(loaf.warnings, flapjack.warnings)    assert in_either == [Hazard.gluten, Hazard.milk, Hazard.sesame]    assert set.intersection(loaf.warnings, [Hazard.sesame, Hazard.nuts]) == [Hazard.sesame]    assert set.difference(loaf.warnings, [Hazard.sesame]) == [Hazard.gluten]    assert safe_for(flapjack, [Hazard.nuts])    assert not safe_for(loaf, [Hazard.nuts, Hazard.sesame])    assert tray_warnings([loaf, flapjack]) == [Hazard.milk, Hazard.sesame, Hazard.gluten]    assert label(loaf.warnings) == [Hazard.gluten, Hazard.sesame]}

Two sets are equal when they hold the same items, whatever the order, so the literal on the right of == can be written in any order. Walking a set is the only place its order shows, and it is always the canonical order, on every target.

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