in reply to Implementing a cyclic array

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.