in reply to Is there a "better" way to cycle an array?

Here is another way to do it, inspired by hdb's answer, but with a function that takes the array you want to cycle through as a parameter (instead of having a sub that remembers both the array and the associated position for each array). The positions are stored in a hash which uses the stringified arrayref as a key.

I've added some extra food for thoughts: using *cycle to be able to call the sub without the -> notation. blessing one arrayref into the current package to call the function as a method. Or, using the + prototype on a function that calls $sub->() to be able to call cycle2 on either an array ref or a literal array.

use strict; use warnings; sub makeClosure { my %pos; # hash that will store the positions of all the array +s return sub { my $array = shift; $pos{$array} //= -1; # To avoid "Use of uninit +ialized value" $pos{$array} = (($pos{$array})+1) % @$array; return $array->[$pos{$array}]; } } my $sub = makeClosure; my $array1 =[1..4]; my $array2 = ['a'..'c']; $\ = $/; print $sub->($array1) for 1..3; print $sub->($array2) for 1..2; print $sub->($array1) for 1..3; print $sub->($array2) for 1..2; print "__________"; print "Unblessed reference : ", $array2; *cycle = $sub; # &main::cycle is now our closure use subs 'cycle'; # Tell Perl that there is a function called cycle, b +ecause there was no 'sub cycle'. # This is only useful if you want to call cycle with +out parenthesis bless $array2; # $array2 is now an object of class 'main' print "Blessed reference : ", $array2; print cycle $array2; # this works because of use subs print $array2->cycle() for 1..3; # calls main::cycle on object $array2 sub cycle2(+) { my $array = shift; $sub->($array); } print "__________"; print cycle2 $array1; my @array = qw/Tic Tac/; print cycle2 @array for 1..4;
1 2 3 a b 4 1 2 c a __________ Unblessed reference : ARRAY(0x10eb6a0) Blessed reference : main=ARRAY(0x10eb6a0) a b c a __________ 3 Tic Tac Tic Tac
As you may notice, when blessing a reference, its stringified version changes to include the class. So in this case, the cycling starts back at position 0.