sub make_iter {
my @values = @_;
my $idx = -1;
return sub {
# check if we are out of values,
# return a value or undef if we're out
return (++$idx > $#values) ? undef : $values[$idx];
}
}
my $iter = make_iter(3,4,6,7);
print while( $_ = $iter->() );
####
sub make_iter_deeper {
my @AoA = @_;
my @idx;
my $i = 0; # keeping it simple
$idx[0] = -1; # same as $idx = -1 above;
my @return;
return sub {
# if the index of the array i'm working in is
# past the end of elements
if ( ++$idx[$i] > $#{@{$AoA[$i]}} ) {
return;
}
# if not, put the next element in the return value
else {
$return[$i] = $AoA[$i][$idx[$i]]
}
return @return;
}
}
my $iter = make_iter_deeper([3,4,6,7]);
print join(',',@_) . "\n" while( @_ = $iter->() );
##
##
sub make_iter_deeperer {
my @AoA = @_;
my @idx;
my $i = -1;
$idx[0] = -1;
my @return;
return sub {
# depth first to produce "nested" result behavior
# if we aren't at the end of AoA's elements, go to
# the next, reseting the next elements' index
if( $i < $#AoA ) {
$idx[++$i]= -1;
}
LOOP: {
if ( ++$idx[$i] > $#{@{$AoA[$i]}} ) {
# if the index of the array i'm working in is
# past the end of elements it means we need to
# go up a level and clear the last return value
pop @return;
# we may have finished everything
return if --$i < 0;
# we may have finished more than one
# so check again
redo LOOP;
}
# if not, put the next element in the return value
else {
$return[$i] = $AoA[$i][$idx[$i]]
}
}
return @return;
}
}
##
##
sub _NL_Iter
{
my( $loops, $code, $when )= @_;
my @list;
my $i= -1;
my @idx;
my @vals= @$loops;
return sub { return }
if ! @vals;
return sub {
while( 1 ) {
# Prepare to append one more value:
if( $i < $#$loops ) {
$idx[++$i]= -1;
if( isa( $loops->[$i], 'CODE' ) ) {
local( $_ )= $list[-1];
$vals[$i]= $loops->[$i]->(@list);
}
}
## return if $i < 0;
# Increment furthest value, chopping if done there:
while( @{$vals[$i]} <= ++$idx[$i] ) {
pop @list;
return if --$i < 0;
}
$list[$i]= $vals[$i][$idx[$i]];
my $act;
$act= !ref($when) ? $when : do {
local( $_ )= $list[-1];
$when->(@list);
};
return @list if $act;
}
};
}