継続渡し形式
find-foldからfind-fold2への書き換えでいきなりつまずいてたけど、やっと理解できてきたかも。
指定した条件を満たす要素だけfoldするfind-foldは、素直に書くと以下のようになる。
(define find-fold (lambda (pred? proc seed lis) (cond ((null? lis) seed) ((pred? (car lis)) (find-fold pred? proc (proc (car lis) seed) (cdr lis))) (else (find-fold pred? proc seed (cdr lis))))))
2番目のcond節で、(car lis)とseedにprocを適用して、その結果(戻り値)でfind-foldを再帰させている。
procの結果が戻ってくるので、章のはじめにあったC社のCall-Return方式だ。
渡されたリストの中から奇数を探して、その総和を求めるには以下のようにする。
gosh> (define add (lambda (elt seed) (+ elt seed))) add gosh> (find-fold odd? add 0 '(1 2 3 4 5 6 7 8 9 10)) 25
これに対し、S社の継続渡し方式では、
- 計算に必要な情報(Call-Return方式でのeltとseed)
- 計算結果を渡す宛先
を一緒に渡してやるので、以下のようになる。
(define find-fold2 (lambda (pred? proc/cont seed lis) (cond ((null? lis) seed) ((pred? (car lis)) (proc/cont (car lis) seed (lambda (seed2) (find-fold2 pred? proc/cont seed2 (cdr lis))))) (else (find-fold2 pred? proc/cont seed (cdr lis))))))
proc/contが
- eltとseedで計算(proc)をする
- 計算結果を次の工程(cont)に渡す
をやってくれるところで、具体的に書くと
(define add/cont (lambda (elt seed cont) (cont (+ elt seed))))
で、find-fold2で使ってみると、次のとおり。
gosh> (find-fold2 odd? add/cont 0 '(1 2 3 4 5 6 7 8 9 10)) 25
計算結果を持って、ずんずんと深く入り込んでいくイメージがようやくつかめてきた。