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

Here's what I believe to be a "correct" implementation although it doesn't work with my copy of pugs.

It's a slightly functional way of doing it. (Assuming my understanding of lexically-scoped subs is correct) I set up a recursive "incrementer" function which increments one position of @pos and "carries over" via a recursive call. It's tail-recursive, so if the compiler is smart, we don't lose a lot by making it recursive instead of iterative.

sub NestedLoops (*@loop) returns Ref { my @pos = 0 xx (@loop.elems - 1), -1; my sub incr($i) { if ( ++@pos[$i] == @loop[$i].elems ) { @pos[$i] = 0; return $i ?? incr($i - 1) :: 0; } return 1; }; return sub { incr(@loop.end) or return; zip(@loop, @pos) ==> map -> $a, $i { $a[$i] }; }; }; my $iter = NestedLoops( [0..2], [0..2] ); my @group; while ( @group = $iter() ) { say ~@group; }
From what I can tell, there are two things currently holding back pugs: You can fix that by just substituting Limbic~Region's map statement for the line containing zip. I was hoping there would be an even easier way to write this line. Something like:
@loops >>.[]<< @pos
But pugs didn't like that..

blokhead

Replies are listed 'Best First'.
Re^2: Perl6 Contest #2: P6 That Doesn't Look Like P5
by kelan (Deacon) on Jun 03, 2005 at 13:09 UTC

    You can always simulate your own n-ary map using gather:

    gather { for @loop Y @pos -> $arr, $i { take $a[ $i ]; } }
    Although allowing map to take multiple items from the list at once would be nicer, and it's something I've wanted rather often.

      Although allowing map to take multiple items from the list at once would be nicer, and it's something I've wanted rather often.

      Sure, works in current Pugs! :)

      @result = map { $^a + $^b } 1,2,3,4; # 3,7 @result = map -> $a, $b { $a + $^b } 1,2,3,4; # 3,7 # And: $result = reduce { $^a + $^b * $^c } 1,2,3,4,5; # same as $result = (1 + 2 * 3) + 4 * 5; # i.e. # 27

      --Ingo

Re^2: Perl6 Contest #2: P6 That Doesn't Look Like P5
by kelan (Deacon) on Jun 03, 2005 at 18:39 UTC

    If you have your trusty zipwith available:

    sub zipwith ( Code $with, *@lists ) { gather { while any( @lists ) { take $with.( @lists>>.shift ); } } }
    then you can change that zip line to:
    zipwith( { $^a[ $^i ] }, @loop, @pos );