(Lispex)sicp.io
3.2 · Closures and locations

Each closure can own a private location.

Two procedures made by the same constructor can execute the same code while remembering different bindings.

Guiding question

Why do two counters made by one procedure not overwrite each other?

  • Connect a closure to the environment where it was created
  • Separate equal procedure code from distinct stored locations
  • Predict observations from shared and private bindings

Each call to make-counter creates a new value binding and returns a procedure that keeps access to it. left and right share the lambda expression, but they do not share that binding.

The second example moves value outside both procedures. That single location is then shared, so an update through either procedure becomes the starting point for the other.

Lispex · SICP sourceScheme-compatible SICP syntax executed by the Lispex SICP profile.
(begin
  (define (make-counter start)
    (let ((value start))
      (lambda ()
        (set! value (+ value 1))
        value)))
  (let ((left (make-counter 0))
        (right (make-counter 10)))
    (list (left) (left) (right) (left) (right))))
Lispex learning runtimeLispex SICP profile 1.0.0
Loading Lispex SICP runtime
Lispex · SICP source246 / 1,048,576 UTF-8 bytes
Examples
Result
Output
Value
Diagnostic
Visible execution0 / 0 trace events
    This browser result is not a Lispex Vouch record or authority.wasm —
    Expected observation

    The first program returns (1 2 11 3 12).

    Trace focus

    Compare the two make-counter applications with the later calls to left and right. The repeated lambda body reaches the location captured by its own creation environment.

    Try it yourself

    Change the program before you read the hint.

    Create a third counter starting at 100. Interleave all three counters and predict which calls can affect one another.

    Show one hint

    Count calls to make-counter. Each call creates one new private value binding.