{ package Iterator::Filter; sub new { my $self = bless {}, shift; $self->{'iterator'} = shift; $self->{'condition'} = shift; $self->reset; $self } sub reset { my $self = shift; $self->{'iterator'}->reset; $self->_advance; } # post-condition: either # a. iterator is not at end, and value is set; or # b. iterator is at end, and value is not set. sub _advance { my $self = shift; my @value; delete $self->{'value'}; while ( !$self->{'iterator'}->is_exhausted ) { @value = $self->{'iterator'}->value; if ( $self->{'condition'}->( @value ) ) { $self->{'value'} = \@value; last; } } } sub value { my $self = shift; $self->is_exhausted and die "past end"; my $value = $self->{'value'}; $self->_advance; @$value } sub is_exhausted { my $self = shift; !exists $self->{'value'} } }