ええ、継続はかなり気が遠くなる可能性があります。これは私がしばらく前に見つけた良いパズルです - 何が印刷されているのか、なぜ印刷されているのかを理解してみてください:
(define (mondo-bizarro)
(let ((k (call/cc (lambda (c) c)))) ; A
(write 1)
(call/cc (lambda (c) (k c))) ; B
(write 2)
(call/cc (lambda (c) (k c))) ; C
(write 3)))
(mondo-bizarro)
これがどのように機能するかの説明 (ネタバレを含みます!):
- 最初の
call/cc
ストアはそれ自身の継続を返し、それを に格納しk
ます。
- 番号
1
が画面に書き込まれます。
- 点 B で継続する現在の継続は k に戻され、k は A に戻ります。
- 今度は、k は B で取得した継続にバインドされます。
- 番号
1
が画面に再度書き込まれます
- 点 B で継続する現在の継続は、別の点 B への別の (ただし異なる) 継続である k に戻されます。
- 元の継続に戻ったら、ここで k がまだ A にバインドされていることに注意することが重要です。
- 番号
2
が画面に書き込まれます
- 点 C で継続する現在の継続は、k に戻され、k は A に戻ります。
- 今度は、k は C で取得した継続にバインドされます。
- 番号
1
が画面に再度書き込まれます
- 点 B で継続する現在の継続は k に戻され、k は C に戻ります。
- 番号
3
が画面に書き込まれます
- そして、あなたは終わった
したがって、正しい出力は11213
です。私が太字で示した最も一般的な問題点 - 継続を使用して k の値を「リセット」する場合、元の継続の k の値に影響を与えないことに注意することが重要です。それがわかると、より理解しやすくなります。