2

Lisp( GitHubのコード)を書いていますが、ローカルバインディングを実装したいと思います。現在、2つの構文があります。

(let <var> <val> <expr>)

単一の変数または関数をバインドするため、および

(with (<var1> <val1> ... <varN> <valN>) <expr>)

一度に複数の値をバインドします。

現在、バインディングは順番に評価され、新しい関数バインディングはそれぞれ、定義された環境のコピーを保持しているため、<var2>参照することはできますが<var1>、その逆はできません。

複数の値を一度にバインドするときに、効果的に同時にバインドできるようにコードを変更したいと思います。たとえば、次のように記述できるようにしたいと思います(これは簡単な例ですが、アイデアを説明する必要があります)。

(define (h y)
  (with ((f x) (if (eq? x 0) #t (g (- x 1)))
         (g x) (if (eq? x 0) #f (f (- x 1))))
  (f y))

現時点では、このコードは実行されません-g終了しますがf、その逆はありません。

Lispで同時バインディングを実装する標準的な方法はありますか?

4

2 に答える 2

1

SICPには、この主題をカバーする内部定義に関するセクションがあります。特に、演習4.16、4.18、4.19では、同時定義を実現するためのさまざまな戦略を実装する方法を説明しています。

構文は少し異なりますが、本のアイデアは、このコードを変換することに要約されます。

(lambda <vars>
  (define u <e1>)
  (define v <e2>)
  <e3>)

このコードに:

(lambda <vars>
  (let ((u '*unassigned*)
        (v '*unassigned*))
    (set! u <e1>)
    (set! v <e2>)
    <e3>))

同じ考え方があなたのwith特別なフォームにも当てはまります。実装の詳細については、リンクされた本を参照してください。

于 2012-04-22T21:36:04.540 に答える
1

式の値に(with (a (+ 2 2)))バインドしているので、4になります。しかし、他のことをしている場合、関数にバインドしています。これはの構文糖衣です。a(+ 2 2)a(with ((f x) (+ x x)))f(with (f (lambda (x) (+ x x))))

この状況を処理するには、2つのパスでバインディングを処理する必要があります。まず、すべての変数を収集し、それらすべてを含む環境を作成します。次に、初期化エクスプレッションを評価し、それらの値を対応する変数に格納します。これらの式の評価はその環境で行われるため、すべての式がすべての変数を可視化します。初期化は割り当てによって行われます。変数は、最初に設定するnilことも、アクセスすると爆発するトラップ値を持つこともできます。

于 2012-04-22T21:36:47.680 に答える