継続渡しで実行を制御する
find-foldで済むものを、なぜ手間をかけてfind-fold2にするのか。
それは外から与えられるproc/contを少しいじるだけで、find-fold2の実行を制御できるからだ、と。
ということで、コード例をば。次のようなnextとbreakとadd/breakを定義して、
(define next #f) (define break (lambda (e) e)) (define add/break (lambda (elt seed cont) (set! next (lambda () (print "found: " elt) (cont (+ elt seed)))) (break #f)))
次のようにfind-fold2に与えてやると、面白いことが起こる。
gosh> (find-fold2 odd? add/break 0 '(1 2 3 4 5 6 7 8 9 10)) #f gosh> (next) found: 1 #f gosh> (next) found: 3 #f gosh> (next) found: 5 #f gosh> (next) found: 7 #f gosh> (next) found: 9 25
検索結果を1ずつ見れるようになりましたとさ。
すごい!find-fold2の定義を変更せずにこんなことが!すごい!
何が起きているのかよくわからなかったので、ちょっと追ってみた。
- find-fold2の実行→proc/contの実行→nextを更新→#fが返る
- REPLへ戻る
- nextの実行→contの実行→find-fold2の実行→proc/contの実行→nextを更新→#fが返る
- REPLへ戻る
- nextの実行→contの実行→find-fold2の実行→proc/contの実行→nextを更新→#fが返る
- (中略)
- REPLへ戻る
- nextの実行→contの実行→find-fold2の実行→proc/contの実行→nextを更新→#fが返る
- REPLへ戻る
- nextの実行→contの実行→find-fold2の実行→lisが空→seedが返る
なるほどねぇ...。動きは理解はできたけど、書けと言われてもちょっと無理かなぁー。