in reply to Perl6 Contest #2: P6 That Doesn't Look Like P5

All,
I hacked in support for OnlyWhen and \&Code from Algorithm::Loops.
use v6; sub NestedLoop (++@loop, +$OnlyWhen, +$code) returns Ref{ my @pos = 0 xx (@loop.elems - 1), -1; return sub { my @group; loop { if ++@pos[-1] > @loop[-1].end { for reverse 0 .. @pos.end - 1 -> $i { next if @pos[$i] == @loop[$i].end; ++@pos[$i]; @pos = (@pos[0..$i], 0 xx (@pos.end - $i)) and las +t; } } return () if @pos[-1] > @loop[-1].end; @group = map -> $i { @loop[$i][@pos[$i]] } 0 .. @pos.end; if $OnlyWhen.does(Code) { $OnlyWhen(@group) or next } $code(@group) if $code.does(Code); last; } return @group; }; }; my $next = NestedLoop(loop => ([0..2], [0..2], [0..2])); my @group; while @group = $next() { say ~@group; }
If anyone is having a hard time following my logic in order to come up with alternatives, ask and I will provide an explanation. The basic idea is counting where each position relates to an anonymous array and the base to count in for that position is dependent on that array.

Cheers - L~R

Replies are listed 'Best First'.
Re^2: Perl6 Contest #2: P6 That Doesn't Look Like P5
by eric256 (Parson) on Jun 03, 2005 at 05:45 UTC

    Could you run throught the logic of that code? I see some changes i wanted to make but then i get lost in the code. ;) Thanks.


    ___________
    Eric Hodges
      eric256,
      Sure! First I will give an explanation of how the logic works and then a blow by blow of how the code accomplishes that logic. The code is a bit trickier because we added in a few options:

      Cheers - L~R

        I took a rather different approach to the code. I love OO so i went that route.

        #!/usr/bin/pugs use v6; class MultiCounter { has @.positions is rw; has @.lengths is rw; submethod BUILD() { @.positions = (0) xx (@.lengths.end + 1); } method inc () returns Bool { @.positions[-1]++; for reverse (0..@.lengths.end - 1) -> $i { if (@.positions[$i + 1] > @.lengths[$i + 1]) { @.positions[$i]++; @.positions[$i + 1] = 0; } } return (@.positions[0] > @.lengths[0]) ?? 0 :: 1; } } class NestedLoops { has @.loops is rw; has MultiCounter $.counter is r; submethod BUILD() { $.counter = MultiCounter.new( :lengths( @.loops.map:{.end } +) ); } method inc () returns Bool { $.counter.inc; } method data () { my @data; for (0..@.loops.end) -> $i { push @data, @.loops[ $i ][$.counter.positions[$i]]; } return @data; }; } my $counter = NestedLoops.new( :loops(['a','b'],[0..2], ['one',2,3]) ) +; while ($counter.inc) { $counter.data.join(" ").say; }

        Some refinements and added features would probably be good but this is my start.


        ___________
        Eric Hodges