On the principle that ugly working code is better than elegant nonworking code, I did a brute-force conversion of part of
Algorithms:Loop. It supports a last-in-the list-parameter the hard way, by copying it as the first parameter instead of in
$_,
use v6;
sub _NL_Iter(@loops, $when) returns Ref {
my @list;
my $i = -1;
my @idx;
return sub { return }
if ! @loops;
my @vals = @loops;
return sub {
while 1 {
# Prepare to append one more value:
if $i < @loops.end {
@idx[++$i]= -1;
if @loops[$i].does(Code) {
@vals[$i]= @loops[$i](@list[-1], @list);
}
}
## return if $i < 0;
# Increment furthest value, chopping if done there.
while @vals[$i].elems <= ++@idx[$i] {
pop @list;
return if --$i < 0;
}
@list[$i]= @vals[$i][@idx[$i]];
if $when.does(Code) {
return @list if $when(@list[-1], @list);
} else {
return @list;
}
}
};
}
sub NestedLoop(++@loops, +$code, +$when) {
my $onlywhen = $when;
my $count_elems = @loops.elems + 1;
$onlywhen //= sub { @_ == $count_elems }; # Default case - when we
+have a full count.
my $iter= _NL_Iter(@loops, $onlywhen );
if ! $code {
# There seeems to be no way to check for void context, since
# want.count is not working. I wanted to test want.count == 0
+.
return $iter;
}
my @ret;
my @list;
while @list = $iter() {
@list = $code( @list );
if want.List {
push @ret, @list;
} else {
@ret[0] += @list;
}
}
return want.List ?? @ret :: ( $ret[0] // 0 );
}
my $next = NestedLoop(loops => ([0..2], [0..2], [0..2]));
my @group;
while @group = $next() { say ~@group; };
say "\nsecond case:";
my $N = 4;
my $depth = 3;
my $i2 = NestedLoop(loops => ( [ 0..$N ],
( sub { [@_[0]+1..$N] } ) xx ($depth-
+1),
) );
while @group = $i2() { say ~@group; };