The sample below tries to make a "cartesian supergenerator" that takes several smaller generators and combines them into a larger generator that yields cartesian combinations of the results.
This works on the first pass (when the result of g1=1). But when the result of g1=2, the g2 generator is already spent, and produces no more values. Of course, it would be possible to precache the results of each generator into a list and then combine those cartesian-style. But that would defeat the laziness of the evaluation. (Assume the individual generators conduct expensive operations.) The ultimate idea is to do as little work as possible, but then having done it, avoid repeating it. (This could be the mantra of my entire programming career.) #lang racket (require racket/generator rackunit) (define/contract (make-cartesian-generator gens) ((listof generator?) . -> . generator?) (generator () (let loop ([gens gens][sols empty]) (cond [(empty? gens) (yield (reverse sols))] [else (match-define (cons gen rest) gens) (for ([sol (in-producer gen (void))]) (loop rest (cons sol sols)))])))) (define g1 (generator () (yield 1) (yield 2) (void))) (define g2 (generator () (yield 'a) (yield 'b) (void))) (check-equal? (for/list ([gs (in-producer (make-cartesian-generator (list g1 g2)) (void))]) gs) '((1 a) (1 b) (2 a) (2 b))) -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.