package Tie::Array::SubIterator; use base Tie::Array; sub TIEARRAY { my $class = shift; my %in = @_; $in{'length'} = -1 unless $in{'length'} && $in{'length'} =~ /^\d$/; die "Expected coderef for next option" unless ref($in{'next'}) eq "CODE"; die "Expected coderef for determine_end option" unless !defined($in{'determine_end'}) or $in{'length'} < 0 or ref($in{'determine_end'}) eq "CODE"; $in{'determine_end'} = sub { return defined(+shift->{'last_result'}) ? 0:1; } if (!$in{'determine_end'} && $in{'length'} < 0); $in{'last_counted'} = 0; $in{'ended'} = 0; my $self = bless \%in, $class; eval { $self->{'last_result'} = $self->{'next'}->($self,0) if $self->{'length'} < 0; }; $self->{'ended'} = 1 if $@; return $self; } sub FETCH { my $self = shift; return $self->{'next'}->($shift,@_) if ($self->{length} > -1); my $last = $self->{'last_result'}; eval { $self->{'last_result'} = $self->{'next'}->($self,++$_[0]) unless $self->{'ended'}; }; $self->{'ended'} = 1 if $@; return $last; } sub FETCHSIZE { $self = shift; return $self->{'length'} if $self->{'length'} > -1; ++$self->{'last_counted'} unless ($self->{'ended'}) || ($self->{'ended'} = $self->{determine_end}->($self)); $self->{'last_counted'}; } sub DESTROY { my $self = $_[0]; $self->{destroy}->(@_) if ref($self->{destroy}) eq "CODE"; } 1;