Python風ジェネレータを限定継続で

ここでいろいろ議論されてる、call/ccを使ったジェネレータを勉強がてらに限定継続で書き直してみる。トリッキーな部分がなくなって、かなり素直に書ける。

(define (make-generator f)
  (let ((cont #f))
    (lambda ()
      (reset (if cont
                 (cont #f)
                 (f (lambda (v) (shift k (set! cont k) v))))))))

(define (fib-generator)
  (make-generator
   (lambda (yield)
     (let loop ((a 1) (b 1))
       (yield a)
       (loop b (+ a b))))))

動作は以下のとおり。

> (define fib (fib-generator))
> (list (fib) (fib) (fib) (fib) (fib))
(1 1 2 3 5)
> 

限定継続って、"composable continuation"とも呼ばれてるのね。個人的にはそっちの方がしっくりするように思う。継続サーバとかでもてはやされてて、限定継続は「限定的である」ことばかりが重要視されてるような気がするけれど(勝手な思い込み?)、継続の呼び出しが大域脱出にならないことも限定継続の柔軟性のためのポイントじゃないでしょか。前回とは真逆のことを言ってるわけだけど;-P

まぁ、もうちょっと勉強する価値はありそう。meta continuationとshift/resetの実装についてはまだ頭の中を整理中。まとめ(られ)るかは未定。