http://www.perlmonks.org?node_id=122728


in reply to Let's get lazy

tilly once posted something that could be coerced to do this.

Update: It would be kind of the inside-out solution to this problem, you could get a function callback for every combination of values, but I think to get an actual iterator function using this method, similar to the iterator produced by my $iter = do { my $i; sub { $i++ } };, you'd need a co-routine. Unless tilly can wrangle it out of his code :-)

There does seem to be a Coroutine Module on CPAN, might be fun to look into :)

Update: Taking the initiative, I wrangled tilly's code myself (just couldn't wait for the book :)

use strict; use warnings; my $iterator = mk_iter( [1..2], ["a".."c"], [3..5] ); while (my @arr = $iterator->()) { print "@arr\n"; } sub mk_iter { my $range = shift; my $i = 0; my $end = @$range; my $iter = sub { return unless $i < $end; return $$range[$i++]; }; @_ ? ret_iter($iter, @_) : $iter; } sub ret_iter { my $iter = shift; my $range = shift; my $i = 0; my $end = @$range; my @arr; my $new_iter = sub { $i = 0 unless $i < $end; return unless $i or @arr = $iter->(); return @arr, $$range[$i++]; }; @_ ? ret_iter($new_iter, @_) : $new_iter; } ##################################### # Update # Here's a variation which is closer to what was # Originally asked for, i.e. all combinations from # 2-4 characters use strict; use warnings; use strict; use warnings; my $iterator = make_iter( 2,4,[qw(A C G N T)] ); while (my @arr = $iterator->()) { print "@arr\n"; } sub make_iter { my ($start, $end, $range) = @_; my $nxt_iter = sub { return }; my $iter = sub { my @data; unless (@data = $nxt_iter->()) { return unless $start <= $end; $nxt_iter = mk_iter( ($range) x $start++); return $nxt_iter->(); }; @data; } }