soma.cell

Functional record updates: with / without / merge produce new records without mutating the original

Demonstrates immutable-style field updates and that the source record is left untouched.

A Soma program from the records part of the verified corpus: 51 lines, cells RecordOps, RecordOpsTest. It passes soma check with soma 3.2.4.

How it is built

The cell RecordOps declares 5 signals in its face: base() -> Map, promoted() -> Map, anonymized() -> Map, merged() -> Map and source_unchanged() -> Bool. Handlers: base (line 14), promoted (line 19), anonymized (line 24), merged (line 29) and source_unchanged (line 33).

The file also holds 1 test cell (RecordOpsTest) with 7 assertions, run by soma test.

Generated from soma describe on this file.

The source

record_ops.cell

// Functional record updates: with / without / merge produce new records
// without mutating the original. Demonstrates immutable-style field updates
// and that the source record is left untouched.

cell RecordOps {
    face {
        signal base() -> Map
        signal promoted() -> Map
        signal anonymized() -> Map
        signal merged() -> Map
        signal source_unchanged() -> Bool
    }

    on base() {
        return User { name: "Ada", role: "member", age: 30 }
    }

    // with() returns a copy with a field replaced/added.
    on promoted() {
        return base() |> with("role", "admin")
    }

    // without() returns a copy with keys removed.
    on anonymized() {
        return base() |> without("name", "age")
    }

    // merge() overlays a second map (right wins on conflict).
    on merged() {
        return merge(base(), map("age", 31, "city", "London"))
    }

    on source_unchanged() {
        let b = base()
        let p = b |> with("role", "admin")
        return b.role == "member" && p.role == "admin"
    }
}

cell test RecordOpsTest {
    rules {
        assert promoted().role == "admin"
        assert base().role == "member"
        assert anonymized().role == "member"
        assert len(without(base(), "name")) == 3
        assert merged().age == 31
        assert merged().city == "London"
        assert source_unchanged() == true
    }
}

What the toolchain says

Run on a fresh copy of the program at build time; the outputs are pasted unedited.

$ soma check record_ops.cell
✓ All checks passed.
$ soma test record_ops.cell
test RecordOpsTest ...
  ✓ assert promoted().role == "admin"
  ✓ assert base().role == "member"
  ✓ assert anonymized().role == "member"
  ✓ assert len(without(base(), "name")) == 3
  ✓ assert merged().age == 31
  ✓ assert merged().city == "London"
  ✓ assert source_unchanged() == true

7 tests: 7 passed, 0 failed
$ soma verify record_ops.cell
Verifying record_ops.cell...
No state machine in this program: nothing to prove beyond `soma check` (invariants and lifecycles are what verify proves).
VERIFY OK (vacuous — no state machine)

Builtins used

len, map, merge, with, without

Source file: /corpus/records/record_ops.cell · examples/corpus/records/record_ops.cell