soma.cell

Lesson 2 — Guess wrong, read the fix

A lesson of the course on the Soma programming language. Every output on this page was printed by soma 3.2.4: the build writes each file to an empty folder and runs each command.

Here is what a model writes on its first try, carrying the habits of Python and JavaScript:

cart.cell

cell Shop {
    memory { carts: Map<String, Map> [persistent] }
    on add(user: String, sku: String) {
        let cart = carts.get(user) ?? {}
        cart[sku] = (cart[sku] ?? 0) + 1
        carts.set(user, cart)
        return cart
    }
}
$ soma check cart.cell
error: expected expression, found '{'
  --> cart.cell:4:39
  |
4 |         let cart = carts.get(user) ?? {}
  |                                       ^
  hint: Soma has no `{k: v}` literal — a map is `map("k", v)` (empty: `map()`), a record is `Name { k: v }`
  = code: E1001

The error says what to write. After that fix, the next mistakes show up:

cart.cell

cell Shop {
    memory { carts: Map<String, Map> [persistent] }
    on add(user: String, sku: String) {
        let cart = carts.get(user) ?? map()
        if cart[sku] == null { cart[sku] = 0 }
        cart[sku] = cart[sku] + 1
        carts.set(user, cart)
        return cart
    }
    on count(user: String) {
        return len(cart)
    }
}
$ soma check cart.cell
error: 'null' does not exist in Soma — Soma's null is `()`: `if x == () { … }`, `x ?? default`
  --> cart.cell:5:25
  |
5 |         if cart[sku] == null { cart[sku] = 0 }
  |                         ^
  = code: E0091
error: undefined variable 'cart' (did you mean 'carts'?) — no let, parameter, loop variable, match binding or memory slot with that name is in scope
  --> cart.cell:11:20
   |
11 |         return len(cart)
   |                    ^
  = code: E0011
✗ 2 error(s), 0 warning(s).

soma check reports every error it finds in one pass, each with a stable code (soma explain E0091). Fix them and run the program:

cart.cell

cell Shop {
    memory { carts: Map<String, Map> [persistent] }
    on add(user: String, sku: String) {
        let cart = carts.get(user) ?? map()
        cart[sku] = (cart[sku] ?? 0) + 1
        carts.set(user, cart)
        return cart
    }
    on count(user: String) {
        return len(carts.get(user) ?? map())
    }
}
$ soma check cart.cell
✓ All checks passed.

$ soma run cart.cell add ada book
{"book": 1}

$ soma run cart.cell add ada book
{"book": 2}

$ soma run cart.cell count ada
1

That is the loop: write, soma check, apply the fix it names. It converges because the messages are written for the reader who acts on them, and that reader is you.