Each closure can own a private location.
Two procedures made by the same constructor can execute the same code while remembering different bindings.
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.
(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))))- Output
- —
- Value
- —
- Diagnostic
- —
The first program returns (1 2 11 3 12).
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.
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.