(Racket) generatorでFizzBuzz
racketにもgeneratorライブラリがあるので、前回のgaucheのコードを移植……しようとした。しかしracketのgeneratorは汎用ストリームのように使うには、どうにも使いづらかった……。
steramとの相互変換が出来ればもっと楽できそうなんだけど。
#lang racket (require racket/generator) (require srfi/1) (define (circular n s) (sequence->repeated-generator (cons s (make-list (- n 1) "")))) (define (giota) (infinite-generator (let loop ((n 0)) (yield n) (loop (+ n 1))))) (define (generator->list g n) (unfold (λ(a)(zero? (cdr a))) (λ(a)((car a))) (λ(a)(cons (car a) (- (cdr a) 1))) (cons g n))) (define (gfizzbuzz) (let ((g (infinite-generator (let loop ((gens (list (giota) (circular 3 "Fizz") (circular 5 "Buzz")))) (yield (match (map (λ(g)(g)) gens) ((list n "" "") n) ((list _ f b) (string-append f b)))) (loop gens))))) (g) ; drop 1 g)) ;; usage example ;; (generator->list (gfizzbuzz) 100)
追記 (2014/10/7)
for系syntaxや、シーケンスライブラリ in-xxx を使うともう少し綺麗に書けそう。
#lang racket (require racket/generator) (define (circular n s) (sequence->repeated-generator (cons s (make-list (- n 1) "")))) (define (generator->list g n) (for/list ((i (in-naturals)) #:break (>= i n)) (g))) (define (gfizzbuzz) (define gens (list (circular 3 "Fizz") (circular 5 "Buzz"))) (let ((g (generator () (for ((i (in-naturals))) (yield (match (map (λ(g)(g)) gens) ((list "" "") i) ((list f "") f) ((list "" b) b) ((list f b) (string-append f b)))))))) (g) ; drop 1 g)) (generator->list (gfizzbuzz) 100)