sub iter {
my $vals = \@_;
my $i = 0;
sub {
$i >= @$vals ? do { $i = 0; undef } : $vals->[$i++];
};
}
sub enumerate_iter {
local $Data::Dumper::Indent = 0;
local $Data::Dumper::Terse = 1;
my ($iter) = @_;
my $i = 0;
while (defined($_ = $iter->())) {
printf "%2d: (%s)\n", $i++, Dumper($_);
}
print "\n";
}
enumerate_iter( iter( qw[a b c] ) );
# 0: ('a')
# 1: ('b')
# 2: ('c')
####
sub iter_to_seq {
my ($iter) = @_;
sub {
my $val = $iter->();
defined $val ? ($val) : ();
};
}
sub seq_to_iter {
my ($seq) = @_;
sub {
my @val = $seq->();
@val ? [@val] : undef;
};
}
enumerate_iter(
seq_to_iter( iter_to_seq( iter( qw[a b c] ) ) )
);
# 0: (['a'])
# 1: (['b'])
# 2: (['c'])
##
##
use List::Util qw( reduce );
sub seq_prod {
no warnings 'once';
reduce { seq_prod2($a,$b) } @_ ;
}
sub seq_prod2 {
my ($s, $t) = @_;
my @sval;
sub {
my @tval;
while ( !@sval || !(@tval = $t->()) ) {
return () unless @sval = $s->();
}
( @sval, @tval );
};
}
sub iter_prod {
seq_to_iter( seq_prod( map iter_to_seq($_), @_ ) );
}
##
##
my $abcees = iter(qw(a b c));
my $xyzees = iter(qw(x y z));
enumerate_iter(
iter_prod( $abcees, $xyzees )
);
# 0: (['a','x'])
# 1: (['a','y'])
# 2: (['a','z'])
# 3: (['b','x'])
# 4: (['b','y'])
# 5: (['b','z'])
# 6: (['c','x'])
# 7: (['c','y'])
# 8: (['c','z'])
##
##
my $product = iter_prod( $abcees, $xyzees );
while (defined (my $vals = $product->())) {
my @vars = @$vals;
print "Got vars: @vars\n";
# do real work here
}
# Got vars: a x
# Got vars: a y
# Got vars: a z
# Got vars: b x
# Got vars: b y
# Got vars: b z
# Got vars: c x
# Got vars: c y
# Got vars: c z