(let ([x (call/cc (lambda (k) k))])
(x (lambda (ignore) "hi"))) => "hi"
この継続の実行ステップをどのように書くことができますか?
(let ([x (call/cc (lambda (k) k))])
(x (lambda (ignore) "hi"))) => "hi"
この継続の実行ステップをどのように書くことができますか?
演算子は、現在の継続call/cc
で特定のプロシージャを呼び出すために使用されます(したがって、名前が付けられます)。したがって、それがどのように機能するかを理解するには、現在の継続が何であるかを知る必要があります。call-with-current-continuation
あなたのプログラムでは、call/cc
が実行された時点で、継続は次のようになります。
CONT = (let ([x HOLE])
(x (lambda (ignore) "hi")))
ここHOLE
で、プラグインする値のプレースホルダーです。つまり、継続は残りの計算です。進行したい場合は、継続に値を貼り付けることができます。
次に、call/cc
この継続をキャプチャして、プロシージャに渡します(lambda (k) k)
。このプロシージャは、ただちに継続を返すことがわかります。したがって、プログラムは次のようになります。
(let ([x CONT])
(x (lambda (ignore) "hi")))
によってキャプチャされた継続を適用するとcall/cc
、現在の計算が、指定した値でプラグインされた継続に置き換えられます。したがって、アプリケーションは次の(x (lambda (ignore) "hi"))
ようになります。
(let ([x (lambda (ignore) "hi")])
(x (lambda (ignore) "hi")))
残りは、ラムダとアプリケーションについて既に知っていることに従う必要があります。
最初の行では、受信したパラメーターに[x (call/cc (lambda (k) k))]
バインドされた新しい継続を作成しています。それが返され、ローカル変数にバインドされます。したがって、継続です。k
lambda
k
x
x
2 行目でx
は、単一の引数で呼び出されますlambda
。引数は無視され、呼び出しの結果はで(lambda (ignore) "hi")
あり"hi"
、これが継続の結果として最終的に返されます。これは単純に以下を呼び出すのと同じです:
(call/cc
(lambda (k)
(k "hi")))
この式が "hi" と評価されるのはなぜですか?
(let ([x (call/cc (lambda (k) k))])
(x (lambda (ignore) "hi")))
最初のステップは、どのようk
に見えるかを決定することです。
(define k
(lambda (value)
(let ((x value))
(x (lambda (ignore) "hi")))))
これは次と同じであることがすぐにわかります。
(define k
(lambda (x)
(x (lambda (ignore) "hi"))))
しかし、私は1つの小さな詳細について言及するのに失敗しました. が呼び出された場合k
は、末尾の位置で呼び出されたかのようになります。
したがって、によって構築された(f (k 3))
すべての継続については と同じです。それはいつも少しトリッキーです。k
call/cc
(k 3)
lambda^
したがって、それが導入する関数が末尾の位置にあるかのように呼び出されることを意味するために使用しましょう。
(define k
(lambda^ (x)
(x (lambda (ignore) "hi"))))
何が何であるかk
がわかったので、 から戻るに(call/cc (lambda (k) k))
は実際にはデフォルトが使用されていることも知っておく必要があります。
のように正しく書かれているはずです。
(call/cc (lambda (k) (k k))).
に渡されるラムダ式の本体の先頭には、常に k の暗黙の呼び出しがありますcall/cc
。
私たちは何が何でk
あるかを知っています。
x
したがって、これは (読みやすくするために、引数の位置にある を に変えてみましょう) と同じでなければならないことがわかりy
ます。
((lambda^ (x) (x (lambda (ignore) "hi")))
(lambda^ (y) (y (lambda (ignore) "hi"))))
したがって、両方の位置を関数に評価します。
関数の位置で関数を呼び出したら完了lambda^
です。
((lambda^ (x) (x (lambda (ignore) "hi")))
(lambda^ (y) (y (lambda (ignore) "hi"))))
に評価され、代入x
((lambda^ (y) (y (lambda (ignore) "hi")))
(lambda (ignore) "hi"))
もう 1 ステップ、代わりにy
につながる
((lambda (ignore) "hi") (lambda (ignore) "hi"))
、その引数を無視して「こんにちは」を返します