Synsemadocsv0.6.xENES

Cookbook

Cookbook

Copy-paste patterns. Each is complete and doctested elsewhere — start here, then follow the link.

Validate input, keep partial results — and update every row§

Validate a payload into a typed value; sum the valid ones and skip the bad ones with try/recover. Then change every row of a table: lists and maps are values, so each r in rows + set r[…] would only change the loop's copy. Build the new rows with apply + merge, give them back, and set rows to … in the caller:

cookbook.syn
-- Doc cookbook: validate a payload into a typed value, and sum valid ones with
-- partial results (try/recover skips the bad ones); then update every row of a
-- table the value-semantics way. Copy-paste-ready patterns.
intent: "doc cookbook: validate + partial results + update rows"

type Order
    id: number
    total: number

task validate_order(payload)
    when "total" not in payload
        raise("missing total")
    when payload["total"] < 0
        raise("total must be >= 0")
    give Order(payload["id"], payload["total"])

task bad_order()
    give validate_order({"id": 2, "total": -5})

task safe_total(payloads)
    let total be 0
    each p in payloads
        try
            let o be validate_order(p)
            set total to total + (total of o)
        recover err
            log "skipped: " + err          -- partial results: skip the invalid ones
    give total

-- Lists and maps are values: `each r in rows` + `set r[...]` would change a copy.
-- Build the new rows and give them back.
task with_discount(rows, pct)
    give apply((r) => merge(r, {"total": r["total"] * (100 - pct) // 100}), rows)

print("safe_total of mixed orders → " + text(safe_total([{"id": 1, "total": 10}, {"id": 2, "total": -1}, {"id": 3, "total": 5}])))

test "validate accepts good input and rejects bad"
    assert_eq(total of validate_order({"id": 1, "total": 100}), 100)
    assert_error(bad_order)
    assert_error(() => validate_order({"id": 3}))

test "partial results: invalid orders are skipped"
    assert_eq(safe_total([{"id": 1, "total": 10}, {"id": 2, "total": -1}, {"id": 3, "total": 5}]), 15)

test "update every row: build new rows, the original stays as it was"
    let rows be [{"id": 1, "total": 200}, {"id": 2, "total": 50}]
    let cheaper be with_discount(rows, 10)
    assert_eq(cheaper, [{"id": 1, "total": 180}, {"id": 2, "total": 45}])
    assert_eq(rows[0]["total"], 200)
    set rows to with_discount(rows, 10)
    assert_eq(rows, cheaper)

The other patterns (each fully shown on its page)§

Every snippet on those pages is doctested against this version, so an LLM can copy one and it works.