Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm toying with the idea of trying to implement multiple iterator variables in a foreach loop, a la RFC 173. what would be the best way to approach this? At the moment I can only think of source filters, but perlguts makes references to PERL_MAGIC_defelem : vtbl_defelem : Shadow "foreach" iterator variable / smart parameter. So maybe it's possible to use xs for this? I was also thinking about pythonic slices, e.g. $a[0..10:3] would return every third element. Thoughts?

Edit: g0n - code tags

Replies are listed 'Best First'.
Re: best way to implement multiple foreach iterator variables?
by BrowserUk (Patriarch) on Feb 19, 2006 at 07:00 UTC

    For a pure perl solution I use my mapn function to iterate lists in groups. You can use within a for loop also, though it requires array ref syntax to access the elements of the group. I find this a bonus as it means I can use the flexibility of array slices:

    #! perl -slw use strict; sub mapn (&$@) { my( $code, $n, ) = ( shift, shift ); map { $code->( @_[ $_ .. $_ + $n -1 ] ); } map $n * $_, 0 .. ( $#_ / $n ); } use constant { A => 0, B => 1, C =>2, D => 3, E => 4 }; for my $iters ( mapn{ \@_ } 5, 0 .. 99 ) { printf "%d %d %d %d\n", @{ $iters }[ A, C, E, D ]; } __END__ C:\test>junk 0 2 4 3 5 7 9 8 10 12 14 13 15 17 19 18 20 22 24 23 25 27 29 28 30 32 34 33 35 37 39 38 40 42 44 43 45 47 49 48 50 52 54 53 55 57 59 58 60 62 64 63 65 67 69 68 70 72 74 73 75 77 79 78 80 82 84 83 85 87 89 88 90 92 94 93 95 97 99 98

    The constants aren't necessary, but allow for clarity through symbolic names.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: best way to implement multiple foreach iterator variables?
by chromatic (Archbishop) on Feb 19, 2006 at 08:26 UTC

    Perl Hacks shows a similar trick with Want's howmany(). Basically you wrap another iterator around the first and kick the original iterator sufficient times. (Hm, seems kinda monadic.)

    I think that's sort of what you were asking, but now I'm not quite sure.

Re: best way to implement multiple foreach iterator variables?
by dragonchild (Archbishop) on Feb 19, 2006 at 13:11 UTC
    my $cur_index = 0; while ( $cur_index <= $#x - 1 ) { my ($x, $y) = @x[$cur_index .. $cur_index + 1]; $cur_index += 2; # Do stuff with $x and $y }

    If you want the aliasing capabilities, look into Data::Alias.

    As for the neat P6 syntax (for @x -> $x, $y { ... }), you'll be needing a source filter for that.


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

      I like List::MoreUtils natatime for this sort of task:

      use List::MoreUtils qw( natatime ); my $next_two = natatime 2, @x; while ( my ( $x, $y ) = $next_two->() ) { # do something with $x & y };