Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Mutable Cells

Everything so far has been immutable: cons builds a new pair, let binds a name once, and no operation changes a value after it exists. Mutation enters through exactly one door — the cell, a first-class mutable reference:

(cell-new 42)
;=> #<cell 0>

cell-new allocates a cell holding a value; cell-read fetches the current contents; cell-set! replaces them, returning the new value:

(let c (cell-new 0)
  (let _ (cell-set! c (+ (cell-read c) 1))
    (cell-read c)))
;=> 1

(The (let _ effect body) shape is the idiom for sequencing — there is no begin.)

Identity

A cell is a reference: copies alias, and a write through one alias is visible through all. eq? on cells compares identity, not contents — two cells holding the same value are still different cells:

(eq? (cell-new 5) (cell-new 5))
;=> 0
(let c (cell-new 5) (eq? c c))
;=> 1

The printed form #<cell N> shows the cell’s index in the evaluator’s store, which is exactly its identity. The store belongs to the evaluator instance, and persists across top-level forms — the one exception to the rule that nothing outlives a form. A closure over a cell is therefore the floor’s object: state plus behaviour,

(let c (cell-new 100)
  (let counter (lambda _ _ (cell-set! c (+ (cell-read c) 1)))
    (let _ (counter 0)
      (let _ (counter 0)
        (cell-read c)))))
;=> 102

Cells never fold

One rule about cells reaches forward into everything after this chapter: cells never fold under staging. lift of a cell is an error — a residual program cannot capture a live mutable reference as syntax — and staged cell operations always residualize as operations, never evaluate away to the cell’s current contents. A generated program that reads a cell reads it when it runs, not when it was generated.

The rule is why the tower of Part IV works at all: each level of the tower keeps its machinery — its evaluation handlers, its environment — in cells, and a collapsed tower must still see a handler rebinding (via EM) take effect afterward. Fold the cell and the rebinding would be compiled away; keep it a cell and the compiled tower stays honestly reflective. The full mechanics are in Parts II and IV; what to remember from this chapter is that a cell is a promise the compiler keeps.