Evaluation Models Workshop
Trace real programs -- on paper or in a doc -- through the substitution model and the environment model. Spot the exact point where the two disagree. Do this workshop before the interpreter clinic; it directly sets up the mental model you will implement there.
Retrieval Prompts
Answer closed-book:
- State the substitution rule for a procedure application in one sentence.
- State the environment-model rule for a procedure application in one sentence.
- When do the two models disagree?
- In the environment model, what does a procedure value actually contain?
Part A -- Pure Programs, Both Models Agree
Trace each program in the substitution model, step by step, until you reach a value. Then trace the same program in the environment model, drawing every frame and its parent pointer.
Program A1: Square of Sum
(define (square x) (* x x))
(define (sum-of-squares x y) (+ (square x) (square y)))
(sum-of-squares (+ 1 2) (* 3 4))
- Substitution trace: show every reduction step (applicative order).
- Environment trace: draw GLOBAL with
squareandsum-of-squaresbound, then a frame for thesum-of-squarescall, then the two nestedsquareframes.
Program A2: Tail Recursion
(define (iter count acc)
(if (= count 0) acc (iter (- count 1) (* count acc))))
(iter 4 1)
- Substitution: each reduction should reuse one slot, not grow.
- Environment: frames should not stack -- the tail call reuses the frame.
Part B -- Closures, Where Substitution Starts To Strain
Program B1: make-adder
(define (make-adder n) (lambda (x) (+ x n)))
(define a5 (make-adder 5))
(define a7 (make-adder 7))
(+ (a5 10) (a7 10))
- In the environment model: draw GLOBAL with
make-adder,a5,a7bound. Eacha5/a7points to a frame that holdsn. Follow the chain for(a5 10)and confirmnresolves to 5. - In the substitution model: substitute aggressively. Notice that to explain
a5, you must treat it as the expression(lambda (x) (+ x 5)). You can limp through because there is no mutation.
Part C -- Mutation, Where Substitution Breaks
Program C1: Counter
(define (make-counter)
(let ((n 0))
(lambda () (set! n (+ n 1)) n)))
(define c1 (make-counter))
(define c2 (make-counter))
(c1) (c1) (c2) (c1)
- Environment trace: draw all frames. Confirm
c1andc2point at different frames; mutations to one do not affect the other. - Substitution: attempt a trace. You will fail. Write a one-sentence description of where you got stuck.
Program C2: Shared State
(define n 0)
(define (tick) (set! n (+ n 1)) n)
(tick) (tick) (tick)
- Environment trace: one frame, three mutations. Easy.
- Substitution: attempt. Fail. Articulate why in one sentence.
Part D -- Applicative vs Normal Order
(define (try p q) (if (= p 0) 1 q))
(try 0 (/ 1 0))
- Applicative order: show what happens. (It explodes.)
- Normal order: show what happens. (It returns 1.)
- Rewrite
tryto take two thunks ((lambda () 1),(lambda () (/ 1 0))) so that applicative order is safe. Trace once more.
Part E -- Quiz-Prep Trace
Trace this program fully in the environment model. At each step, note which procedure is in tail position and which is not.
(define (fact n)
(if (= n 0) 1 (* n (fact (- n 1)))))
(define (fact-iter n acc)
(if (= n 0) acc (fact-iter (- n 1) (* n acc))))
(fact 3)
(fact-iter 3 1)
Predict which of the two runs in constant space. Confirm by looking at your drawn frames.
Evidence Check
This workshop is complete only if:
- For A1 and A2 you have two traces each, one in each model.
- For B1 your environment diagram shows two separate frames, one per
make-addercall. - For C1 and C2 you have written, in plain English, why substitution fails.
- For D you have the two contrasting traces and the thunked rewrite.
- For E you have identified the tail-position call in
fact-iterand confirmed that the environment model predicts constant space.