The code in Algorithm::Odometer::Tiny is indeed tiny, but loops over lists/arrays not subs. (like the other listed solutions)
Well, part of the idea of the module was to have the code small and simple enough so that it can be copy & pasted into other code. This simple patch allows you to produce your expected output from your shown input:
croak "no wheels specified" unless @_; - my @w = map { [ 1, ref eq 'ARRAY' ? @$_ : $_ ] } @_; + my @w = map { [ 1, ref eq 'CODE' ? $_->() : $_ ] } @_; my $done;
You can of course do the same kind of mapping simply before calling the sub, as in odometer( map { ref eq 'CODE' ? [$_->()] : $_ } ... ), that'd allow you to use the other modules as well.
Of course, it's a different story if the subs passed to the function are to be called as iterators themselves? Update: That'd look something like this:
sub odometer { die "no wheels specified" unless @_; my @w = map { [ $_, $_->() ] } @_; my $done; return sub { if ($done) { $done=0; return } my @cur = map { $_->[1] } @w; for ( my $i=$#w; $i>=0; $i-- ) { defined( $w[$i][1] = $w[$i][0]->() ) and last; $w[$i][1] = $w[$i][0]->(); $done=1 unless $i; } return wantarray ? @cur : join '', map {defined()?$_:''} @cur; }; }
use Test::More; sub array_it { my ($i,@arr) = (0,@_); return sub { if ( $i>$#arr ) { $i=0; return } $arr[$i++] } } { my $odo = odometer( array_it('foo','bar'), array_it('-'), array_it(3..5) ); my @o; while (defined( my $x = $odo->() )) { push @o, $x } while (my @x = $odo->()) { push @o, \@x } is_deeply \@o, ["foo-3", "foo-4", "foo-5", "bar-3", "bar-4", "bar-5", ["foo","-","3"], ["foo","-","4"], ["foo","-","5"], ["bar","-","3"], ["bar","-","4"], ["bar","-","5"] ]; } { my $odo = odometer( array_it(qw/ a b c /), array_it(qw/ 1 2 /,undef,qw/ 3 4 /), ); my @o; while (defined( my $x = $odo->() )) { push @o, $x } is_deeply \@o, [qw/ a1 a2 b3 b4 c1 c2 /]; @o = (); while (defined( my $x = $odo->() )) { push @o, $x } is_deeply \@o, [qw/ a3 a4 b1 b2 c3 c4 /]; } done_testing;
In reply to Re^3: Efficient but elegant Cross-Product iterator ? (updated)
by haukex
in thread Efficient but elegant Cross-Product iterator ?
by LanX
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |