How about a general purpose functional solution.
use Carp; # so mapn can croak about errors
sub mapn (&$@) {
my ($sub, $n, @ret) = splice @_, 0, 2;
croak '$_[1] must be >= 1' unless $n >= 1;
while (@_) {
local *_ = \$_[0];
push @ret, $sub->(splice @_, 0, $n)
}
@ret
}
sub by ($@) {mapn {[@_]} shift, @_}
sub every ($@); *every = \&by;
The mapn
function works just like map
, except the first argument after its block is the number of elements to take. It places the first element in $_
and all of the elements in @_
.
print mapn {"@_\n"} 2 => 1 .. 5;
# prints
1 2
3 4
5
The next two identical subs, by
and every
create useful adverbs for the various looping constructs. They process the list with mapn, and return a list of array refs of the desired size
print "@$_\n" for every 2 => 1..10;
print map {"@$_\n"} grep {$_->[1] > 5} by 2 => 1..10;
I find this to be a cleaner and more intuitive solution than natatime, or other one off solutions like a c style for loop.