1

私は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)))

前もって感謝します!

4

1 に答える 1

3

広告1)

これは予想される動作です。表示されたエラーメッセージは次のとおりです。

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

これnumV-nはの1つでしたnum+。これは、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 に答える