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

Greetings Monks,
I wish to write a small script for work, and I want to try to do it as correctly as possible the first time around. One of the things I'm trying to do is define a range of numbers 1..X with a variable that will cycle through that list in a for loop. For example, it will count from 1 to 4, but then once it gets incremented again ($i++ in a loop for example), it goes straight back to 1 and not 5.
I thought about doing something like:

if ( $i > 4 ) { $i = 1; }

And vice versa for when $i is < 1. Is there a more elegant solution for this?

Replies are listed 'Best First'.
Re: "Round Robin" variable range?
by hdb (Monsignor) on Jan 31, 2014 at 11:26 UTC
      Awesome, thanks guys, the code provided by kcott and hdb fit the bill for what I need. Thanks a lot!
Re: "Round Robin" variable range?
by johngg (Canon) on Jan 31, 2014 at 11:50 UTC

    One way is to use a closure to create a subroutine reference, this is a simpler version of anonymonk's &make_rollover.

    $ perl -Mstrict -Mwarnings -E ' > my $cycle = do { > my $val = 0; > sub { return ( ( $val ++ ) % 4 ) + 1; }; > }; > > say $cycle->() for 1 .. 10;' 1 2 3 4 1 2 3 4 1 2 $

    I hope this is useful.

    Update: Corrected typo, s/ue/use/

    Cheers,

    JohnGG

Re: "Round Robin" variable range? (range operator / modulus )
by Anonymous Monk on Jan 31, 2014 at 11:17 UTC

    range operator loops

    my $whatever = 1; while( $whatever ){ for my $ix ( 1 .. 4 ){ ... } }

    modulus operator "cycle" through array

    sub make_rollover { my( $completion_list ) = @_; my $ix = -1; my $xx = @$completion_list - 1; sub { $ix++; return $completion_list->[ $ix % $xx ]; }; } my $rollover = make_rollover( \@tlud ); while ( my $next = $rollover->() ){ ... }

    There may exist helper modules on cpan to embody these type of ... algorithm loops ...

    Buy, sell, self, sleep, me :Drooooool

Re: "Round Robin" variable range?
by kcott (Archbishop) on Feb 01, 2014 at 03:26 UTC

    G'day Salamihawk,

    Welcome to the monastery.

    If @range holds your range of numbers and $i is initialised to zero, you can cycle through your numbers with:

    $range[$i++ % @range]

    Here's my test:

    #!/usr/bin/env perl -l use strict; use warnings; my @range = 1 .. 4; my $i = 0; for (1 .. 9) { print $range[$i++ % @range]; }

    Output:

    1 2 3 4 1 2 3 4 1

    -- Ken

Re: "Round Robin" variable range?
by Laurent_R (Canon) on Jan 31, 2014 at 16:40 UTC
    You could also use the ternary operator:
    my $i = 0; # ... somewhere in the code: $i = $i < 4 ? $i + 1 : 0;
    The $i variable will cycle on 0, 1, 2, 3, 4, 0, 1, 2 ...