Yet another way to do it would be with the List::MoreUtils  each_array or  each_arrayref array iterator generator functions.

The only 'problem' with these functions is that they return the empty list at the end of an iteration cycle to indicate that the cycle has finished, then start the cycle over again with the first array element(s). Because you seem to want to cycle continuously, you would need logic to detect and 'step over' the end condition.

If you want to roll your own custom iterator, here's an approach (actually, something like this is probably on CPAN already somewhere, I just haven't looked – also, the excellent and freely downloadable Higher-Order Perl discusses this technique in great detail):

use warnings; use strict; sub Iterator (&) { return $_[0] } # syntactic sugar per hop sub cyclic_array_iter { my @array = @_; # copy of array to iterate my $i = $[; # iterated array index return Iterator { return } unless @array; # maybe die here? return Iterator { if (@_) { $i = $_[0]; $i = $[ if $i > $#array or $i < $[; return; } my $element = $array[$i++]; $i = $[ if $i > $#array; return $element; }; } use Test::More 'no_plan'; sub play { return "$_[0] likes to play"; } sub eat { return "$_[0] likes to eat"; } sub nap { return "$_[0] likes to nap"; } my @people = qw(tom harry diana nick sally henry); my @activities = (\&play, \&eat, \&nap); my $person = cyclic_array_iter(@people); my $activity = cyclic_array_iter(@activities); for my $name (@people) { is($person->(), $name, "person: $name"); } is($person->(), 'tom', 'wrap: person: tom'); is($person->(), 'harry', 'person: harry'); $person->(0); is($person->(), 'tom', 'after re-indexing: person: tom'); is($person->(), 'harry', 'person: harry'); $person->(-1); is($person->(), 'tom', 'after bad index (-1): person: tom'); is($person->(), 'harry', 'person: harry'); $person->(1 + $#people); is($person->(), 'tom', 'after bad index (1 beyond): person: tom'); is($person->(), 'harry', 'person: harry'); $person->(99_999); is($person->(), 'tom', 'after bad index (big): person: tom'); is($activity->()->($person->()), 'harry likes to play', 'harry,play'); $activity->()->($person->()); is($activity->()->($person->()), 'nick likes to nap', 'nick,nap'); is($activity->()->($person->()), 'sally likes to play', 'sally,play'); is($activity->()->($person->()), 'henry likes to eat', 'henry,eat'); is($activity->()->($person->()), 'tom likes to nap', 'tom,nap');

Output:

>perl cyclic_array_iter_1.pl ok 1 - person: tom ok 2 - person: harry ok 3 - person: diana ok 4 - person: nick ok 5 - person: sally ok 6 - person: henry ok 7 - wrap: person: tom ok 8 - person: harry ok 9 - after re-indexing: person: tom ok 10 - person: harry ok 11 - after bad index (-1): person: tom ok 12 - person: harry ok 13 - after bad index (1 beyond): person: tom ok 14 - person: harry ok 15 - after bad index (big): person: tom ok 16 - harry,play ok 17 - nick,nap ok 18 - sally,play ok 19 - henry,eat ok 20 - tom,nap 1..20

Update: Added link to MJD's HOP.


In reply to Re: Implementing a cyclic array by AnomalousMonk
in thread Implementing a cyclic array by perlpal

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.