Atoms (active-state stores)
An atom holds a single immutable state value and lets you change it
only through transitions — pure reducers (currentState, payload?) → newState. Dispatching a transition computes the next value and swaps the held
one (the old value is dropped). This is the Redux store / Clojure atom model.
state Cart = { items: Integer, total: Number } // an immutable state type
atom cart {
initial Cart { items: 0, total: 0.0 }
transition addItem(s: Cart, price: Number) -> Cart {
return Cart { items: s.items + 1, total: s.total + price }
}
transition clear(s: Cart) -> Cart { return empty Cart }
}
cart.addItem(9.99) // dispatch: next = addItem(current, 9.99); held value swapped
cart.clear()
let n = cart.current.items // read the current immutable snapshot
Semantics
state T = { ... }declares an immutable state type (a compound type; you replace it, never mutate it in place).atom name { initial <value> transition* }declares one holder seeded withinitial.- A
transition f(s: T, p: P) -> Tis a reducer. Callingname.f(p)passes the current state assautomatically — you supply only the payload — then stores the returned value. A transition with no payload is justf(s: T) -> T. name.currentreads the current value.- Time-travel: every transition records the prior state, so
name.undo()reverts to it (returning the restored value) andname.canUndo()reports whether there's anything to revert. History is bounded (the most recent 256 states), so undo can't grow memory without limit.
Notes & limits
- One global instance per
atom(no per-instance stores yet). - Transitions are synchronous and single-threaded.
- A
statewhose fields use onlyString[]/user-type arrays is fine; primitive arrays (Integer[]) aren't supported yet (a general limitation).
A higher-level state machine layer (named states, a legal-transition graph,
machine-wide data, and where guards) is also available — see
Machines.
See examples/atom_demo.xi.