Deferred Substitution
在執行出現with時,利用「substitution」,每次with的出現,它都繞着整個body置換。這一方式是由F1WAE到env再到list-of-FunDef爲止,而後再到substitution列表中,以env的形式進行。
In Case of WAE
DefrdSub
(define-type DefrdSub
[mtSub]
[aSub (name symbol?)
(value number?)
(rest DefrdSub?)])
lookup : symbol DefrdSub -> number
(define (lookup name ds)
(type-case DefrdSub ds
[mtSub () (error 'lookup "free variable")]
[aSub (x val rest) (if (symbol=? x name)
val
(lookup name rest))]))
interp : WAE -> number 換成 WAE DefrdSub -> number
(define (interp wae ds)
(type-case WAE wae
[num (n) n]
[add (l r) (+ (interp l ds) (interp r ds))]
[sub (l r) (- (interp l ds) (interp r ds))]
[with (x i b) (interp b (aSub x (interp i ds) ds))]
[id (s) (lookup s ds)]))
In Case of F1WAE
不經思考,會形成以下後果:
{deffun {f x} {+ y x}}
(interp (parse '{with {y 2} {f 10}})), env:[]
->(interp (parse '{f 10})), env:[y=2]
->(interp (parse '{+ y x})), env:[x=10 y=2]
->12 wrong!
更準確地說,這是static scope不適合的體現。
interp : F1WAE list-of-FunDef DefrdSub -> number
(define (interp f1wae fundefs ds)
(type-case F1WAE f1wae
...
[app (ftn arg)
(local [(define a-fundef (lookup-fundef ftn fundefs))])
(interp (fundef-body a-fundef)
fundefs
(aSub (fundef-arg-name a-fundef)
(interp arg fundefs ds)
(mtSub)))]))
在進行「function call」時,將DefrdSub從新裝入env,使其成爲「arg substitution」。(local設計)