#回答ありがとうございます。
#(call/cc (lambda (return)
(define (yield)
(call/cc (lambda (cont)
(enqueue! *tasks* cont)
(return)))) ; ここに値が返された後、yieldから戻り、body ... が実行されるということですか?
body ...))
; もしそうであれば、なぜ body ... の中身である (print 'one) 最初にyieldをthreeの中で呼び出したときに実行されないのですか?
#処理の流れとして、yieldの中の(call/cc ...) とその後のbody...は繋がってませんよ。
#yieldの後に繋がるのはあくまで、「そのyieldが実際に呼び出された場所」です。
#今現在コールスタック上に乗っている処理を捕捉するのがcall/ccということですか?
混乱してしまい申し訳ございません。
もしyield中のcall/ccがbody ... とつながらないとすれば、どうしてcontは
(lambda ()
(print 'two)
(yiled)
.
.
.)
を捕捉するのですか。全くつながりがないように思えてしまうのですが。
#threeの中で
(let lp ()
(print 'one)
(yield)
(print 'two)
...)
とyieldを呼び出しているからです。最初のyieldの呼び出しが起きた時、次にある処理は(print 'two)ですよね。
この例では、(print 'two) ...などがマクロのbody ... に含まれているので混乱するかもしれませんが、このyield手続きだけを取り出して (e.g. グローバル変数にアサインするなどして)、全く関係ない関数から呼び出しても、その呼び出した関数の残りの処理が継続で捕捉されます。
#そう、「現在コールスタックに乗っている処理を捕捉するのがcall/cc」という理解で正しいです。
#なるほど、それで大体contの部分はわかりました。
つまり、
(define (three)
(call/cc (lambda (return)
(define (yield)
(call/cc (lambda (cont)
(enqueue! *tasks* cont)
(return))))
(print 'one)
(yield)
(print 'two)
(yield))))
とあったとして、(three)を実行すると、まず(print 'one)でoneが表示され、
次に(yield)で現在コールスタックに積まれている手続きつまり(begin (print 'two) (yield))
がcontに捕捉されるということですね。
そこまではよろしいのですが、そうすると今度はreturnの部分の理解があいまいになります。
returnはどのような手続きを捕捉しますか? (print 'one)の後の(yield)を呼び出した際、(return)が最後に呼ばれますが、
ここではどのような手続きが実行されますか?
#returnは外側のcall/ccによって捕まえられる継続です。
(define (three)
(call/cc (lambda (return) ...))
((dequeue! *tasks*)))
となっているので、returnに束縛される継続は
(lambda val ((dequeue! *tasks*))) です。
#回答ありがとうございます。shiroさんのおかげで継続がなんとなくわかりました。
#つまり、「やりたいやりたい」とうめいている手続きにストップをかけて、ほかに制御を移すのが継続ですね。
#ところで、また疑問点があれば質問してもよろしいでしょうか?
#いつでもどうぞ。私がいなくてもここに書いておけば誰かが答えると思います。
#むー、気がついたらgit stashが10個くらい積み重なっててもう底の方は何をしていたんだかさっぱり覚えていない。
#その様子と自分の物理的な机の上との類似性に気づく。そういえば年末に机上も大掃除しようと思って忘れてた。