(use gauche.partcont)
;; 部分継続でcoroutine作ってみる
(define *current-coroutine* ())
(define coroutine-done (list 'coroutine-done))
(define (make-coroutine thunk)
(let ([co (list #f)])
(lambda args
(let ([old *current-coroutine*])
(set! *current-coroutine* co)
(let ([v (if (car co)
(apply (car co) args)
(reset
(thunk)
(set-car! co (lambda _ coroutine-done))
coroutine-done))])
(set! *current-coroutine* old)
v)))))
(define (yield . v)
(shift k
(set-car! *current-coroutine* k)
(unless (null? v) (car v))))
(define-syntax coroutine
(syntax-rules ()
[(_ body ...)
(make-coroutine (lambda () body ...))]))
(let ([co ()])
(set! co
(coroutine
(yield :a)
(yield :b)
(yield :c)))
(print (co))
(print (co))
(print (co))
(print (co))
(print (co)))