Iterator-Flex
view release on metacpan or search on metacpan
lib/Iterator/Flex/Stack.pm view on Meta::CPAN
use experimental qw( signatures declared_refs refaliasing );
our $VERSION = '0.33';
use Iterator::Flex::Utils qw( RETURN STATE EXHAUSTION :IterAttrs :IterStates );
use Iterator::Flex::Factory 'to_iterator';
use parent 'Iterator::Flex::Base';
use List::Util 'all';
use namespace::clean;
sub new ( $class, @args ) {
my $pars = Ref::Util::is_hashref( $args[-1] ) ? pop @args : {};
$class->SUPER::new( {
depends => \@args,
current_iterator_index => undef,
},
$pars,
);
}
sub construct ( $class, $state ) {
throw_failure( parameter => q{state must be a HASH reference} )
unless Ref::Util::is_hashref( $state );
$state->{value} //= [];
my ( \@depends, $prev, $current, undef, undef )
= @{$state}{ 'depends', 'prev', 'current', 'next', 'thaw' };
# transform into iterators if required.
my @stack
= map { to_iterator( $_, { ( +EXHAUSTION ) => RETURN } ) } @depends;
my @snapshot = @stack;
# --- cargo cult??
# my $value;
# $value = $current
# if $thaw;
my $self;
my $iter;
my $is_exhausted;
my $iterator_state;
my sub init {
$iterator_state = IterState_EXHAUSTED;
if ( @stack ) {
$iter = $stack[0];
$is_exhausted = $iter->can( 'is_exhausted' );
$iterator_state = IterState_CLEAR;
}
}
init();
my %params = (
( +_NAME ) => 'istack',
( +_SELF ) => \$self,
( +RESET ) => sub {
$prev = $current = undef;
@stack = @snapshot;
init();
},
( +REWIND ) => sub {
@stack = @snapshot;
init();
},
( +STATE ) => \$iterator_state,
( +NEXT ) => sub {
return $self->signal_exhaustion if $iterator_state == IterState_EXHAUSTED;
while ( 1 ) {
my $value = $iter->();
if ( defined( $value ) || !$iter->$is_exhausted ) {
$prev = $current;
return $current = $value;
( run in 2.211 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )