3

私はスキームを学び、スキームで let* のインタプリタを実装しようとしています。文法は次のとおりです。

<s6> -> <expr>                   
       | <define>
<expr> -> NUMBER | IDENT | <if> | <let> | <letstar> | <lambda> | <application>
<define> -> ( define IDENT <expr> )
<if> -> ( if <expr> <expr> <expr> )
<let> -> ( let ( <var_binding_list> ) <expr> )
<letstar> -> ( let* ( <var_binding_list> ) <expr> )
<lambda> -> ( lambda ( <formal_list> ) <expr> )
<application> -> ( <operator> <operand_list> )
<operator> -> <built_in_operator> | <lambda> | IDENT
<built_in_operator> -> + | * | - | /
<operand_list> -> <expr> <operand_list> | empty
<var_binding_list> -> ( IDENT <expr> ) <var_binding_list> | ( IDENT <expr> )
<formal_list> -> IDENT <formal_list> | IDENT

前に let を実装する方法を学びました。これは次のとおりです。

(define let-stmt? (lambda (e)
(and (list? e) (equal? (car e) 'let) (= (length e) 3))))

(define get-value (lambda (var env)
(cond
    ((null? env) (error "s6-interpret: unbound variable -->" var))
    ((equal? (caar env) var) (cdar env))
    (else (get-value var (cdr env))))))

(define s6-interpret (lambda (e env)     //thanks to GoZooner
(cond
    ((number? e) e)
    ((symbol? e) (get-value e env))
    ((not (list? e)) (error "s6-interpret: cannot evaluate -->" e))

    ((let-stmt? e)
        (let ((names (map car  (cadr e)))
                (inits (map cadr (cadr e))))

        (let ((vals (map (lambda (init) (s6-interpret init env)) inits)))

        (let ((new-env (append (map cons names vals) env)))

        (s6-interpret (caddr e) new-env)))))

let* のインタープリターを作成できるように、let のインタープリターを変更するにはどうすればよいですか? 誰でも助けることができますか?

ありがとう

4

3 に答える 3

2

これは最近何度か聞かれました。Scheme の質問のリストを下にスクロールしてください。要点は次のとおりです。これlet*は構文変換です。この主題について詳しくはSICPを参照してください。「派生式」というタイトルのセクションを探してください。この場合の重要なアイデアは、評価者が次のような式を見つけるたびに、次のようになるということです。

(let* ((a 10)
       (b (+ 10 a)))
  (+ a b))

lambda...次のように簡単に評価できる、同等の一連のネストされたアプリケーションに直接変換できます。

((lambda (a)
   ((lambda (b)
      (+ a b))
    (+ 10 a)))
 10)

または、中間ステップを実行し、最初let*に a を一連のネストされたs に変換してから評価することもできます。これは、特別な形式letを既に実装している場合に役立ちます。let上記と同じ例は次のようになります。

(let ((a 10))
  (let ((b (+ 10 a)))
    (+ a b)))

もちろん、最初にlambdaフォームを評価する方法を知る必要があります。ここで要点は、 と の両方letlet*特殊な形式 (構文糖にすぎない) であり、たとえばプロシージャ アプリケーションの同じ評価モデルには従わず、評価者レベルで特別な処理が必要であるということです。この場合、評価方法がわかっている別の式を生成する構文変換。

于 2013-05-30T19:05:29.877 に答える