続4・PrologでR6RS ~dynamic-wind物語~
dynamic-windが多分できました。
「多分」と付いてるのは、あんまり試してないからです。
そもそも本物のSchemeでdynamic-windなんて使ったことがありませんし(笑)
まずは、dynamic-windの途中で脱出する例。
?- eval([store,[[hoge,0]], [call_cc, [lambda,[k], [dynamic-wind,+, [lambda,[],[k,3]], [lambda,[],[set,hoge,789]] ]] ]], X). X = [store, [[hoge, 789]], [values, 3]] ; No
非常に読みづらいですが、S式に直すと、大域環境が「hoge=0」の時に、
(call/cc (lambda (k) (dynamic-wind + (lambda () (k 3)) (lambda (set! hoge 789))))) => 3 (大域環境は「hoge=789」)
ということです。
dynamic-windを途中で脱出していますが、
第三引数であるサンクがちゃんと適用されているのが分かります(hogeに値が設定されている)。
次に、dynamic-windに再突入する例。
?- eval([store,[[cont,0],[hoge,0]], [dynamic-wind, [lambda,[],[set,hoge,[+,hoge,1]]], [lambda,[],[call_cc,[lambda,[k],[set,cont,k],0]]], +] ], X). X = [store, [[cont, [throw, '#:G866', [begin0|...]]], [hoge, 1]], [values, 0]] ; No ?- eval([store, [[cont, [throw, '#:G866', ... ]], [hoge, 1]], [cont,333]], X). X = [store, [[cont, [throw, '#:G866', [begin0|...]]], [hoge, 2]], [values, 333]] ; No
またも、死ぬほど読みにくいのでS式に直すと、大域環境が「cont=0, hoge=0」の時に
(dynamic-wind (lambda () (set! hoge (+ hoge 1))) (lambda () (call/cc (lambda (k) (set! cont k) 0))) +) => 0 (大域環境は「cont=継続オブジェクト, hoge=1」) (cont 333) => 333 (大域環境は「cont=継続オブジェクト, hoge=2」)
dynamic-windの第二引数のサンクに再突入していますが、
第一引数のサンクが適用されているのが分かります(hogeがインクリメントされている)。
本当は、もっと複雑な例も試すべきなんでしょうが、
評価をしてステップごとの結果を追うのが非常に疲れるのでこれだけで勘弁してください。
多分上手く動いていると思います。