Here's another tied variable solution. I didn't implement most of the tied array methods; it's ill-defined what push, pop, etc. should do in this case.
All told, I think I prefer your solution after blokhead's suggestions.
package Array::AliasRange;
sub TIEARRAY {
my ($class, $array, $offset, $length) = @_;
bless {
array => $array,
offset => $offset,
length => $length,
}, $_[0];
}
sub _real_index {
my ($self, $index) = @_;
if ($index >= 0) {
return undef if ($index + $self->{offset}) >= ($self->{offset} + $
+self->{length});
return $index + $self->{offset};
} else {
return undef if (scalar @{$self->{array}} - ($index + $self->{offs
+et})) < 0;
return scalar @{$self->{array}} - ($index + $self->{offset});
}
}
sub FETCH {
my ($self, $index) = @_;
my $real_index = _real_index($self, $index);
return defined $real_index ? $self->{array}[$real_index] : undef;
}
sub STORE {
my ($self, $index, $newval) = @_;
my $real_index = _real_index($self, $index);
return defined $real_index ? ($self->{array}[$real_index] = $newval)
+ : undef;
}
sub FETCHSIZE {
my $self = shift;
return $self->{length};
}
package main;
sub by_groups_of {
my ($by, $arrayref) = @_;
return sub { () } if ! $by || $by =~ /\D/ || ! @$arrayref;
my $offset = 0;
return sub {
return () if $offset >= scalar @$arrayref;
my @new_array;
my $length = ($offset + $by >= scalar @$arrayref) ? (scalar @$arra
+yref - $offset) : $by;
tie @new_array, "Array::AliasRange", $arrayref, $offset, $length;
$offset += $by;
return \@new_array;
}
}
my @array = 0 .. 10;
my $next = by_groups_of( 3, \@array );
while ( my $group = $next->() ) {
$group->[1] = 'foo';
}
print join ' ', @array, "\n";