2

環境は計画の継続の一部ではありませんか?

私はこれをChicken、Gauche、Racket、Gambitでテストしましたが、それらはすべて同じように動作します。

(define kont #f)

(let ((a 1)
      (b 2))
  (call-with-current-continuation
   (lambda (k)
     (set! kont k)
     (display 'mutating)
     (newline)
     (set! a -1)
     (set! b -2)))
  (display (+ a b))
  (newline))

LETが評価されるときは-3と予想されますが、kontの呼び出しでは+3になります(プログラムはミューテーションの前にaとbのバインディングを記憶していると思ったため)。

(let ... ) ; <-- evaluating the LET above
; prints "mutating"
=> -3
(kont 100)
=> -3
(kont 100)
=> -3

では、継続は制御にのみ影響し、環境には影響しませんか?この場合、継続を実装する方法の1つが「スタックをコピーする」ことであると言われるのはなぜですか(バインディングはスタックにありませんか?)

4

2 に答える 2

3

継続はバインディングをキャプチャします。ただし、ご想像のとおり、これらのバインディングは変更可能です。

ここでは、「スタックをコピーする」というスローガンに誤解されています。これは call/cc を考える上で合理的な方法ですが、それだけではありません。1 つには、ローカル バインディングがスタック割り当てされているかどうかに関係なく公開される言語機能は、実際には必要ありません。

代わりに、call/cc は「プログラム コンテキスト」の概念を使用して定義されます。これを適切に扱うには、Shriram Krishnamurthi の (無料のオンライン) 教科書PLAI、または (無料ではない、より詳細な) 本「Semantics Engineering with PLT Redex」を参照してください。

余談として; キャプチャされた継続を呼び出したことがないため、プログラムは実際にチェックしたいものをチェックしません。私はあなたがこのようなものを書きたかったと思います:

#lang racket

(define kont #f)

(let ([a 3])

  (let/cc k
    (set! kont k)
    (set! a 4))
  (printf "~s\n" a))

(kont)

...これは、上記とほぼ同じ動作を示しています。

于 2011-05-14T15:00:26.650 に答える
1

set! を使用して、環境内の a と b の値を変更します。したがって、継続環境では a と b は -1 と -2 です。副作用を展開することはできません。あなたの継続では、a、b、および kont の間に違いはありません。

于 2011-05-14T14:32:14.660 に答える