無限オブ無限
(use util.queue) (use util.stream) ;; coroutine (define process-queue (make-queue)) (define (coroutine thunk) (enqueue! process-queue thunk)) (define (start) ((dequeue! process-queue))) (define (pause) (call/cc (lambda (k) (coroutine (lambda () (k #f))) (start)))) ;;----- (define (gen s) (lambda () (let loop ((s s)) (unless (stream-null? s) (display (stream-car s)) (display " ") (pause) (loop (stream-cdr s)))))) (define (manager n ss) (lambda () (let loop ((i 0) (ss ss)) (unless (stream-null? ss) (when (< i n) (coroutine (gen (stream-car ss))) (pause) (loop (+ i 1) (stream-cdr ss))))))) (coroutine (manager 10 (stream-map (lambda (x) (stream-iota -1 x 3)) (stream-iota -1)))) (start)
実行結果
0 3 1 6 4 2 9 7 5 3 12 10 8 6 4 15 13 11 9 7 5 18 16 14 12 10 8 6 21 19 17 15 13 11 9 7 24 22 20 18 16 14 12 10 8 27 25 23 21 19 17 15 13 11 9
改行いれて見やすくすると
0
3 1
6 4 2
9 7 5 3
12 10 8 6 4
15 13 11 9 7 5
18 16 14 12 10 8 6
21 19 17 15 13 11 9 7
24 22 20 18 16 14 12 10 8
27 25 23 21 19 17 15 13 11 9
何をやってるかというと、
- 無限ストリームの無限ストリーム ((0 3 6 ...) (1 4 7 ...) (2 5 8 ...) ...) をmanagerに渡す(managerは全体を統括する軽量スレッド)
- まずはmanagerが起動。"(0 3 6 ...) をひとつずつプリントする軽量スレッド"をフォークする。
- "(0 3 6 ...) をひとつずつプリントする軽量スレッド"の順番。0をプリント。
- キューが一巡してmanagerが起動。"(1 4 7 ...) をひとつずつプリントする軽量スレッド"をフォークする。
- "(0 3 6 ...) をひとつずつプリントする軽量スレッド"の順番。3をプリント。
- "(1 4 7 ...) をひとつずつプリントする軽量スレッド"の順番。1をプリント。
- キューが一巡してmanagerが起動。"(2 5 8 ...) をひとつずつプリントする軽量スレッド"をフォークする。
- "(0 3 6 ...) をひとつずつプリントする軽量スレッド"の順番。6をプリント。
- "(1 4 7 ...) をひとつずつプリントする軽量スレッド"の順番。4をプリント。
- "(2 5 8 ...) をひとつずつプリントする軽量スレッド"の順番。2をプリント。
- ... managerのカウンターで終わる。
ナナメに列挙することになります。