私はPLAIの Chapter8 "Implementing Laziness" を勉強していて、以下の CFAE/L を終えました:
(define-type CFAE/L
[num (n number?)]
[add (lhs CFAE/L?)(rhs CFAE/L?)]
[id (name symbol?)]
[fun (param symbol?)(body CFAE/L?)]
[app (fun-expr CFAE/L?)(arg-expr CFAE/L?)])
(define-type CFAE/L-Value
[numV (n number?)]
[closureV (param symbol?)
(body CFAE/L?)
(env Env?)]
[exprV (expr CFAE/L?)
(env Env?)])
(define-type Env
[mtSub]
[aSub (name symbol?)(value CFAE/L-Value?)(env Env?)])
(define (num+ x y) ;; need this because we can't just use Scheme + to add FAE-values
(numV (+ (numV-n x) (numV-n y))))
(define (parse sexp)
(cond [(number? sexp) (num sexp)]
[(symbol? sexp) (id sexp)]
[(list? sexp)
(case (first sexp)
((+)
(add (parse (second sexp))
(parse (third sexp))))
((with)
(app (fun (first (second sexp))
(parse (third sexp)))
(parse (second (second sexp)))))
((fun)
(fun (first (second sexp))
(parse (third sexp))))
(else
(app (parse (first sexp))
(parse (second sexp)))))]))
(define (lookup name env)
(type-case Env env
[mtSub() (error 'lookup "no binding for identifier")]
[aSub (bound-name bound-value rest-ds)
(if (symbol=? bound-name name)
bound-value
(lookup name rest-ds))]))
(define (interp expr env)
(type-case CFAE/L expr
[num (n) (numV n)]
[add (l r)(num+ (interp l env)(interp r env))]
[id (v) (lookup v env)]
[fun (bound-id bound-body)
(closureV bound-id bound-body env)]
[app (fun-expr arg-expr)
(local ([define fun-val (interp fun-expr env)]
[define arg-val (exprV arg-expr env)])
(interp (closureV-body fun-val)
(aSub (closureV-param fun-val)
arg-val
(closureV-env fun-val))))]))
このインタープリターによると、page76 の
{with {x 3} {+ x x}}
(1) 入力時:
(interp (parse '{with {x 3} {+ xx}}) {mtSub}) 以下のようなエラーが発生しました:
numV-n: 契約違反、期待値: numV?、指定: (exprV (num 3) (mtSub)) 契約元: numV-n、非難: 使用契約: (-> numV? number?) at: /study/lisp /plai/chapter8.scm:10.9
(2) page76 の説明を理解するために、次のように手順を手書きで書き留めておきたいと思います。これらを処理します: それ (および同様に他の算術プリミティブ) は、式のクロージャが対応する数を正確に知る必要があります。」私のステップがあります: (interp (parse '(with (x 3) (+ xx))) (mtSub))
step1: (parse '(with (x 3) (+ xx))) => (app (fun 'x (add (id 'x) (id 'x))) (num 3))
NOTE: fun-exp is (fun 'x (add (id 'x), arg-expr is (num 3)
step2: (cloSureV 'x (add (id 'x) (id 'x)) (mtSub)) (as fun-val)
and (experV (num 3) (mtSub)) (as arg-val)
step3: (interp (add (id 'x) (id 'x)) (aSub 'x (num 3) (mtSub)))
前もって感謝します!