1

私はスキームのスキーム評価器に取り組んでいます。let を実装する必要があります。変数名、入力する値、および関数の本体が得られるように解析しました。解析された情報を使用してラムダ関数を返す必要があるため、次のコードがあります。

(define (eval-let exp env)
  ((lambda (let-variables (let-bindings exp)) (let-body exp)) (let-exp (let-bindings exp))))

(let-variables (let-bindings exp)) は変数名のリスト (例: '(xy)) に評価されるため、基本的には次のように評価します。

((lambda '(x y) (* x y)) '(2 3))

スキームインタープリターは単純に次のように述べています: #%plain-lambda: not an identifier in: (let-bindings exp) は、値のリストではなく、一連の識別子が必要なためだと推測しています。

値のリストを一連の識別子に変換するにはどうすればよいですか?

4

1 に答える 1

1

独自のインタープリターで式を実装するletには、最初にそれをアプリケーションに変換する必要がありますlambda。これは次のようなものです (プロシージャー名は自明である必要があります)。

(define (let->combination exp)
  (let* ((bindings (let-bindings exp))
         (body     (let-body exp))
         (exps     (bindings-all-exps bindings))
         (lambda   (make-lambda (bindings-all-vars bindings) body)))
    (make-application lambda exps)))

(define (make-lambda parameters body)
  (list* 'lambda parameters body))

(define (make-application proc . args)
  (cond ((null? args) (list proc))
        ((list? (car args)) (cons proc (car args)))
        (else (cons proc args))))

そして、構文変換が実行された、それを評価することができます:

(eval (let->combination exp) env)

私が指摘しようとしているのは、それを直接評価しようとするべきではないということです。また、生成しているコードにはいくつかの間違った引用符があることに注意してください。

((lambda '(x y) (* x y)) '(2 3))
         ^               ^
       here            here

代わりに、次のようになります。

((lambda (x y) (* x y)) 2 3)
于 2014-03-30T23:42:52.250 に答える