1

我正在学习PLAI的第8章“实现懒惰”,并完成了以下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?数字?)在:/study/lisp /plai/chapter8.scm:10.9

(2) 为了理解page76的描述,我想写下步骤如下:“解释器将主体中的每个x评估为表达式闭包(因为这是环境中绑定到x的内容),但添加过程不能处理这些:它(以及类似的任何其他算术原语)需要确切地知道表达式闭包对应的数字。”,但在完成这些步骤后我仍然不清楚这个描述。有我的步骤: (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)))

提前致谢!

4

1 回答 1

3

广告 1)

这是预期的行为。您收到的错误消息是:

 numV-n: contract violation, 
   expected: numV?, 
   given: (exprV (num 3) (mtSub)) 
   ...

numV-nnum+. 这在第 75 页的最后一段中进行了解释。原语如num+预期的非封闭值,但该值(exprV (num 3) (mtSub))是在空环境上封闭的数字 3。

因此,诸如num+必须强制参数的原语。从第 76 页开始:

(define (num+ n1 n2)
    (numV (+ (numV-n (strict n1) ) (numV-n (strict n2) ))))

广告 2)

1) 的解释对 2) 有帮助吗?

添加

为什么不让口译员为您写出步骤?

快速修复:

(define (interp expr env)
      (displayln (list 'expr expr 'env env))
      (type-case CFAE/L expr

为了获得更可读的输出,首先unparse将 CFAE/L 转换为(可读)字符串。

于 2012-07-20T11:20:45.343 回答