PLAI那些事04 Deferred Substitution

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設計)
相關文章
相關標籤/搜索