8

私は Scheme インタプリタを書いていますが、次のような有効な let ステートメントに直面しています:

;; should print 7
(let ((a 4) (b 3))
    (let ((a (* a a)) 
          (b (* b b)))
       (+ a b)
       (- a b)))

私のインタープリターは、Scheme の純粋に機能的なサブセットのみを実装しているため、set! などの副作用はありません。純粋に関数型の言語で、上記のように let ステートメント内で複数の式を許可するのはなぜですか?

インタプリタを書く際に、let の最後の式以外を評価する必要がある理由はありますか? 評価された最後のステートメントの結果に影響を与えることはできなかったようです。

4

3 に答える 3

7

実際には、最後のステートメント以外のすべてを「削除」することはできません。前のステートメントが終了しない可能性があるためです。例えば:

(define (func) (func))

(let ()
  (func) ;; does not return
  1)

ここで、評価しないままにしておく(func)と、間違った結果 (1) が得られますが、終了しない計算が得られるはずです。

もう 1 つの問題は、call/cc (call-with-current-continuation) (そして、機能サブセットに属します) を使用して、末尾以外の位置から実際に計算を返すことができることです。たとえば、次のようになります。

(call-with-current-continuation
  (lambda (ret)
    (let ()
      (ret 3)
      4)))

これは 4 ではなく3を返します。これはまだ純粋に機能しています。

ところで(let () x y z)、単一ステートメント形式と同等であることに注意してください(let () (begin x y z))。実際の問題は、必要かどうかですbegin:)

于 2009-03-17T04:13:52.123 に答える
2

あなたの言う通りです (ほぼ): 純粋に機能的な Scheme のサブセットを実装している場合 (つまり、 no set!, set-car!, set-cdr!)、 a の最後の式以外の式でletは、戻り値が破棄されます。黙って無視しても危険はありません。

ただし、考慮する必要がある小さなケースが 1 つあります。それは、前の式がdefines の場合です。

(let ((x 3))
  (define y 4)
  (+ x y))

これは合法的かつ機能的です。ただし、いくつかの良いニュースがあります。ブロック ( a などlet) 内では、すべてdefineの を先頭に配置する必要があります。のように、これは合法的なスキームとは見なされません。

(let ((x 3))
  (+ 2 3)
  (define y 4)
  (+ x y))

これは、ブロックを評価するとき、あなたがしなければならないことは、defines の先頭をスキャンし、それらを同等のletrec式にラップしてから、最後の式 (それを返す) 以外はすべて無視することです。

編集: antti.huimaは、call/cc について優れた点を指摘しています。実装に継続を含める場合、いつ評価されるかについて多くの仮定を立てることはできません。

于 2009-03-17T04:08:27.673 に答える
1

さて、 は のletようにバインディングを作成しているだけdefineです。バインドされた変数を変更するようなものは何もありませんset!。それでは、名前のスコープを考えてみましょう: a'(+ ab) the same as thea` の は 4 にバインドされていますか? (ヒント:いいえ)

ここでの本当のポイントは、このような厄介なケースでも正しく動作する必要があるということです。スコープとバインディングのルールはシンプルで明確に定義されており、混乱しているように見えるこのようなことを行うのは、それらの結果にすぎません。とのローカルなレキシカル スコープ バインディングを持つletことで、たとえひねくれたサイド ケースがあっても、より明確なプログラムを作成できるため、便利です。

更新 ああ、私はポイントを中断しました。呼び出しが永続的な効果を持たないことは正しいですが(+ a b)、一般的なケースでは、それが真であると仮定することはできません。また、プログラムテキストだけを調べても、それが真であるかどうかを判断することはできません。(考えてみてください: " " の代わりに他の関数が存在する可能性があります+。) ただし、残りの部分については、さまざまな句を評価せずに正しい結果が得られると考えている場合は、letまだ何をしようとしているのかを理解していません。 .

于 2009-03-17T03:38:59.087 に答える