in reply to How to make references more like aliases?

Here's the basics for another approach. (You may extend it the way you feel fit.)

{ package Array::Grouped; sub TIEARRAY { bless { n => $_[1], array => $_[2] } => $_[0] } sub FETCHSIZE { @{$_[0]{array}} / $_[0]{n} } sub FETCH { my $self = shift; my ($i) = @_; my $n = $self->{n}; return sub { \@_ }->(@{$self->{array}}[$i*$n .. $i*$n + $n + - 1]); } } my @bar = 0 .. 9; tie my @foo, Array::Grouped::, 2, \@bar; for (@foo) { $_->[0] = 'x'; } print @bar; # x1x3x5x7x9 ### Update: sub by_groups_of { tie my @foo, Array::Grouped::, @_ } my $foo = by_groups_of(2, \@bar); for (@$foo) { $_->[0] = 'y'; } print @bar; # y1y3y5y7y9
The advantage with this approach is it's memory efficiency and ease of use. If you just want to know e.g. the last or a specific interval you can do that using regular slices. It doesn't consume a lot of memory since it uses the original array and produces the groups when needed.

An overall problem with both this solution and your solution is what to do when the original array is modified, and in particular, spliced upon. Since the problem may be easily solved by hand and you then can explicitly define how you want to handle it, I'm afraid that an abstraction soon will end up with so many options and flags (or limitations) you'd end up with something more complicated than the hand-rolled solution and it's a loss using it. "Over-engineered" comes to mind. That's not to say there are no cases where an abstraction like this is suited.

Personally I find this tie solution to be overkill for everyday use and I would most likely either use my simple &group (see Re: loop thru 3-element array?) or manually set up a for (to handle edge cases). My &group has proven to cover my needs well while being extremely simple. Actually, it's sub pair { group(2, @_) } I most often use and that's when I want to use an each analogy for lists.

Update: Added a wrapper subroutine to show it's just as easy to use as of the other functions in this thread.

ihb

Read argumentation in its context!

Replies are listed 'Best First'.
Re^2: How to make references more like aliases?
by Limbic~Region (Chancellor) on Sep 28, 2004 at 12:31 UTC
    ihb,
    I had thought of a tied solution myself, but it doesn't really fall into the user-friendly category. You have to tie it each time you want to have a different number of elements per loop. As far as the splice problem - I originally copied the array, which is what lead to this post. I mostly handled it since each iteration I check to see if I am falling over the edge - the one case where it could still bite me is if the starting position is already in the abyss. That is easily solved with :
    return () if $done || $pos > $#$list;

    Cheers - L~R

      it doesn't really fall into the user-friendly category

      By adding a simple wrapper subroutine it gets just as user-friendly as the other functions in this thread. See update.

      As far as the splice problem / ... / I mostly handled it since each iteration I check to see if I am falling over the edge

      There are other problems as well. You need to consider whether or not you want unshifts to effect your iterator (after you've done a couple of iterations); compare with foreach's behaviour. What's best here may very well depend on the situation. One solution is to just document that you may not do any size-changing modifications of the original array while using the iterator.

      ihb

      Read argumentation in its context!