view release on metacpan or search on metacpan
            "Test::Spelling" : "0.17",
            "Test::Version" : "1"
         }
      },
      "runtime" : {
         "requires" : {
            "Class::Method::Modifiers" : "0",
            "List::Util" : "1.33",
            "Module::Runtime" : "0",
            "Package::Variant" : "0",
            "Ref::Util" : "0",
            "Role::Tiny" : "2.002004",
            "custom::failures" : "0",
            "experimental" : "0",
            "namespace::clean" : "0",
            "perl" : "v5.28.0"
         }
      },
      "test" : {
         "recommends" : {
            "CPAN::Meta" : "2.120900"
    file: lib/Iterator/Flex/Utils.pm
    version: '0.32'
  Iterator::Flex::Zip:
    file: lib/Iterator/Flex/Zip.pm
    version: '0.32'
requires:
  Class::Method::Modifiers: '0'
  List::Util: '1.33'
  Module::Runtime: '0'
  Package::Variant: '0'
  Ref::Util: '0'
  Role::Tiny: '2.002004'
  custom::failures: '0'
  experimental: '0'
  namespace::clean: '0'
  perl: v5.28.0
resources:
  bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=Iterator-Flex
  repository: https://gitlab.com/djerius/iterator-flex.git
version: '0.32'
x_generated_by_perl: v5.40.3
; --- Project-specific directives
;[AutoPrereqs]
[Prereqs]
Class::Method::Modifiers = 0
List::Util               = 1.33
Module::Runtime          = 0
Package::Variant         = 0
Ref::Util                = 0
Role::Tiny               = 2.002004
custom::failures         = 0
experimental             = 0
namespace::clean         = 0
perl                     = 5.28.0
[Prereqs / ConfigureRequires ]
Module::Build::Tiny      = 0
[Prereqs / TestRequires]
lib/Iterator/Flex/Array.pm view on Meta::CPAN
# ABSTRACT: Array Iterator Class
use v5.28;
use strict;
use warnings;
our $VERSION = '0.32';
use Iterator::Flex::Utils ':IterAttrs', ':IterStates', 'throw_failure';
use Ref::Util;
use namespace::clean;
use experimental 'signatures';
use parent 'Iterator::Flex::Base';
lib/Iterator/Flex/Array.pm view on Meta::CPAN
sub new ( $class, $array, $pars = {} ) {
    throw_failure( parameter => 'argument must be an ARRAY reference' )
      unless Ref::Util::is_arrayref( $array );
    $class->SUPER::new( { array => $array }, $pars );
}
sub construct ( $class, $state ) {
    throw_failure( parameter => q{'state' parameter must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    my ( $arr, $prev, $current, $next )
      = @{$state}{qw[ array prev current next ]};
    throw_failure( parameter => q{state 'array' parameter must be a HASH reference} )
      unless Ref::Util::is_arrayref( $arr );
    my $len = @$arr;
    $next = 0 unless defined $next;
    throw_failure( parameter => q{illegal value for state 'prev' argument} )
      if defined $prev && ( $prev < 0 || $prev >= $len );
    throw_failure( parameter => q{illegal value for state 'current' argument} )
      if defined $current && ( $current < 0 || $current >= $len );
lib/Iterator/Flex/ArrayLike.pm view on Meta::CPAN
# ABSTRACT: ArrayLike Iterator Class
use v5.28;
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.32';
use Ref::Util;
use Iterator::Flex::Utils ':IterAttrs', 'resolve_meth';
use namespace::clean;
use parent 'Iterator::Flex::Base';
lib/Iterator/Flex/ArrayLike.pm view on Meta::CPAN
sub new ( $class, $obj, $pars = {} ) {
    $class->_croak( parameter => q{argument must be a blessed reference} )
      unless Ref::Util::is_blessed_ref( $obj );
    $class->SUPER::new( { object => $obj }, $pars );
}
sub construct ( $class, $state ) {
    throw_failure( parameter => q{state must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    my ( $obj, $prev, $current, $next, $length, $at )
      = @{$state}{qw[ object prev current next length at ]};
    throw_failure( parameter => q{state 'object' argument must be a blessed reference} )
      unless Ref::Util::is_blessed_ref( $obj );
    $length = resolve_meth( $obj, $length, 'length', 'len' );
    $at = resolve_meth( $obj, $at, 'at', 'getitem' );
    my $len = $obj->$length;
    $next = 0 unless defined $next;
    throw_failure( parameter => q{illegal value for state 'prev' argument} )
lib/Iterator/Flex/Base.pm view on Meta::CPAN
# ABSTRACT: Iterator object
use v5.28;
use strict;
use warnings;
use experimental qw( signatures postderef declared_refs );
our $VERSION = '0.32';
use Ref::Util;
use Scalar::Util;
use List::Util;
use Role::Tiny       ();
use Role::Tiny::With ();
use Module::Runtime  ();
Role::Tiny::With::with 'Iterator::Flex::Role';
use Iterator::Flex::Utils qw (
  :default
lib/Iterator/Flex/Base.pm view on Meta::CPAN
    my %ipar = $in_ipar->%*;
    my %gpar = $in_gpar->%*;
    $class->_validate_interface_pars( \%ipar );
    $class->_validate_signal_pars( \%gpar );
    my @roles = ( delete( $ipar{ +_ROLES } ) // [] )->@*;
    $gpar{ +ERROR } //= [THROW];
    $gpar{ +ERROR } = [ $gpar{ +ERROR } ]
      unless Ref::Util::is_arrayref( $gpar{ +ERROR } );
    if ( $gpar{ +ERROR }[0] eq THROW ) {
        push @roles, 'Error::Throw';
    }
    else {
        throw_failure( q{unknown specification of iterator error signaling behavior:}, $gpar{ +ERROR }[0] );
    }
    my $exhaustion_action = $gpar{ +EXHAUSTION } // [ ( +RETURN ) => undef ];
    my @exhaustion_action
      = Ref::Util::is_arrayref( $exhaustion_action )
      ? ( $exhaustion_action->@* )
      : ( $exhaustion_action );
    $gpar{ +EXHAUSTION } = \@exhaustion_action;
    if ( $exhaustion_action[0] eq RETURN ) {
        push @roles, 'Exhaustion::Return';
    }
    elsif ( $exhaustion_action[0] eq THROW ) {
lib/Iterator/Flex/Base.pm view on Meta::CPAN
    }
    else {
        throw_failure( parameter => "unknown exhaustion action: $exhaustion_action[0]" );
    }
    if ( defined( my $par = $ipar{ +METHODS } ) ) {
        require Iterator::Flex::Method;
        throw_failure( parameter => q{value for methods parameter must be a hash reference} )
          unless Ref::Util::is_hashref( $par );
        for my $name ( keys $par->%* ) {
            my $code = $par->{$name};
            throw_failure( parameter => "value for 'methods' parameter key '$name' must be a code reference" )
              unless Ref::Util::is_coderef( $code );
            # create role for the method
            my $role = eval { Iterator::Flex::Method::Maker( $name, name => $name ) };
            if ( $@ ne q{} ) {
                my $error = $@;
                die $error
                  unless Ref::Util::is_blessed_ref( $error )
                  && $error->isa( 'Iterator::Flex::Failure::RoleExists' );
                $role = $error->payload;
            }
            push @roles, q{+} . $role;    # need '+', as these are fully qualified role module names.
        }
    }
    @roles = map { load_role( $_, $class->_role_namespaces ) } @roles;
    $class = Role::Tiny->create_class_with_roles( $class, @roles );
lib/Iterator/Flex/Base.pm view on Meta::CPAN
      if exists $REGISTRY{ refaddr $self };
    my $regentry = $REGISTRY{ refaddr $self } = [];
    # convert to arrays. some of the parameter values are weak
    # references so make sure we don't unweaken them
    my @ipar;
    for my $key ( keys %ipar ) {
        $ipar[ $RegIterationIndexMap{$key} ] = $ipar{$key};
        Scalar::Util::weaken $ipar[ $RegIterationIndexMap{$key} ]
          if Ref::Util::is_ref( $ipar{$key} )
          && Scalar::Util::isweak( $ipar{$key} );
    }
    my @gpar;
    for my $key ( keys %gpar ) {
        $gpar[ $RegGeneralParameterIndexMap{$key} ] = $gpar{$key};
        Scalar::Util::weaken $gpar[ $RegGeneralParameterIndexMap{$key} ]
          if Ref::Util::is_ref( $gpar{$key} )
          && Scalar::Util::isweak( $gpar{$key} );
    }
    $regentry->[REG_ITERATOR] = \@ipar;
    $regentry->[REG_GENERAL]  = \@gpar;
    $self->_clear_state;
    return $self;
}
sub _validate_interface_pars ( $class, $pars ) {
    state %InterfaceParameters = {}->%{ +INTERFACE_PARAMETER_VALUES };
    my @bad = grep { !exists $InterfaceParameters{$_} } keys $pars->%*;
    throw_failure( parameter => "unknown interface parameters: @{[ join ', ', @bad ]}" )
      if @bad;
    throw_failure( parameter => "@{[ _ROLES ]}  must be an arrayref" )
      if defined $pars->{_ROLES} && !Ref::Util::is_arrayref( $pars->{ +_ROLES } );
    if ( defined( my $par = $pars->{ +_DEPENDS } ) ) {
        $pars->{ +_DEPENDS } = $par = [$par] unless Ref::Util::is_arrayref( $par );
        throw_failure( parameter => "dependency #$_ is not an iterator object" )
          unless List::Util::all { $class->_is_iterator( $_ ) } $par->@*;
    }
    return;
}
sub _validate_signal_pars ( $class, $pars ) {
    state %SignalParameters = {}->%{ +SIGNAL_PARAMETER_VALUES };
    my @bad = grep { !exists $SignalParameters{$_} } keys $pars->%*;
lib/Iterator/Flex/Base.pm view on Meta::CPAN
# TODO: this is too restrictive. It should allow simple coderefs, or
# things with a next or __next__.
sub _is_iterator ( $, $obj ) {
    return Ref::Util::is_blessed_ref( $obj ) && $obj->isa( __PACKAGE__ );
}
lib/Iterator/Flex/Base.pm view on Meta::CPAN
                push @values, $self->next;
                if ( $self->is_exhausted ) {
                    pop @values;
                    last;
                }
            }
        }
        1;
    } or do {
        die $@
          unless Ref::Util::is_blessed_ref( $@ )
          && $@->isa( 'Iterator::Flex::Failure::Exhausted' );
    };
    return \@values;
}
1;
#
# This file is part of Iterator-Flex
lib/Iterator/Flex/Cache.pm view on Meta::CPAN
use strict;
use warnings;
use experimental qw( signatures postderef );
our $VERSION = '0.32';
use parent 'Iterator::Flex::Base';
use Iterator::Flex::Utils qw( STATE :IterAttrs :IterStates throw_failure );
use Iterator::Flex::Factory 'to_iterator';
use Scalar::Util;
use Ref::Util;
use namespace::clean;
lib/Iterator/Flex/Cache.pm view on Meta::CPAN
sub new ( $class, $iterable, $pars = {} ) {
    throw_failure( parameter => 'q{pars} argument must be a hash' )
      unless Ref::Util::is_hashref( $pars );
    my %pars = $pars->%*;
    my $capacity = delete $pars{capacity} // 2;
    $class->SUPER::new( {
            capacity => $capacity,
            depends  => [ to_iterator( $iterable ) ],
        },
        \%pars,
lib/Iterator/Flex/Cache.pm view on Meta::CPAN
sub construct ( $class, $state ) {
    throw_failure( parameter => q{state must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    my ( $src, $capacity, $idx, $cache ) = @{$state}{qw[ depends capacity idx cache ]};
    $src = $src->[0];
    $idx   //= -1;
    $cache //= [];
    my $self;
    my $is_exhausted = $src->can( 'is_exhausted' );
    my $iterator_state;
lib/Iterator/Flex/Cat.pm view on Meta::CPAN
sub new ( $class, @args ) {
    my $pars = Ref::Util::is_hashref( $args[-1] ) ? pop @args : {};
    @args
      or throw_failure( parameter => 'not enough parameters' );
    $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, $current_iterator, $prev, $current, $next, undef )
      = @{$state}{ 'depends', 'current_iterator', 'prev', 'current', 'next', 'thaw' };
    # transform into iterators if required.
    my @iterators
      = map { to_iterator( $_, { ( +EXHAUSTION ) => RETURN } ) } @depends;
lib/Iterator/Flex/Chunk.pm view on Meta::CPAN
use v5.28;
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.32';
use Iterator::Flex::Factory 'to_iterator';
use Iterator::Flex::Utils qw[ THROW STATE EXHAUSTION :IterAttrs :IterStates ];
use Ref::Util;
use parent 'Iterator::Flex::Base';
use namespace::clean;
lib/Iterator/Flex/Chunk.pm view on Meta::CPAN
            capacity => $capacity,
            src      => $iterable,
        },
        \%pars,
    );
}
sub construct ( $class, $state ) {
    throw_failure( parameter => q{'state' parameter must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    my ( $src, $capacity ) = @{$state}{qw[ src capacity ]};
    $src
      = to_iterator( $src, { ( +EXHAUSTION ) => THROW } );
    my $self;
    my $iterator_state;
    # This iterator may have to delay signalling exhaustion for one
lib/Iterator/Flex/Chunk.pm view on Meta::CPAN
        ( +NEXT ) => sub {
            return $self->signal_exhaustion
              if $iterator_state == IterState_EXHAUSTED || $next_is_exhausted;
            my @chunked;
            eval {
                push @chunked, $src->() while @chunked < $capacity;
                1;
            } or do {
                die $@
                  unless Ref::Util::is_blessed_ref( $@ )
                  && $@->isa( 'Iterator::Flex::Failure::Exhausted' );
                return $self->signal_exhaustion if !@chunked;
                $next_is_exhausted = !!1;
            };
            return \@chunked;
        },
        ( +RESET ) => sub {
            $next_is_exhausted = !!0;
        },
lib/Iterator/Flex/Common.pm view on Meta::CPAN
our @EXPORT_OK = qw[
  iterator iter iarray ibatch ibuffer icycle icache
  icat ichain ichunk iflatten igather igrep imap
  ipermute
  iproduct iseq istack itake ifreeze izip
  thaw
];
our %EXPORT_TAGS = ( all => \@EXPORT_OK );
use Ref::Util             qw[ is_arrayref is_hashref is_ref is_globref ];
use Module::Runtime       qw[ require_module ];
use Iterator::Flex::Utils qw[ throw_failure ];
use Iterator::Flex::Factory 'to_iterator', 'construct_from_iterable';
lib/Iterator/Flex/Cycle.pm view on Meta::CPAN
# ABSTRACT: Array Cycle Iterator Class
use v5.28;
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.32';
use Iterator::Flex::Utils ':IterAttrs';
use Ref::Util;
use namespace::clean;
use parent 'Iterator::Flex::Base';
lib/Iterator/Flex/Cycle.pm view on Meta::CPAN
sub new ( $class, $array, $ ) {
    throw_failure( parameter => q{argument must be an ARRAY reference} )
      unless Ref::Util::is_arrayref( $array );
    $class->SUPER::new( { array => $array }, {} );
}
sub construct ( $class, $state ) {
    throw_failure( parameter => q{state must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    my ( $arr, $prev, $current, $next )
      = @{$state}{qw[ array prev current next ]};
    my $len = @$arr;
    $next = 0 unless defined $next;
    throw_failure( parameter => q{illegal value for 'prev'} )
      if defined $prev && ( $prev < 0 || $prev >= $len );
lib/Iterator/Flex/Factory.pm view on Meta::CPAN
# ABSTRACT: Create on-the-fly Iterator::Flex classes/objects
use v5.28;
use strict;
use warnings;
use experimental qw( signatures declared_refs refaliasing);
our $VERSION = '0.32';
use Ref::Util        ();
use Role::Tiny       ();
use Role::Tiny::With ();
use Module::Runtime;
use Exporter 'import';
our @EXPORT_OK = qw( to_iterator construct_from_iterable construct_from_attr );
use Iterator::Flex::Base;
use Iterator::Flex::Utils qw[
lib/Iterator/Flex/Factory.pm view on Meta::CPAN
sub construct ( $in_ipar = {}, $in_gpar = {} ) {    ## no critic (ExcessComplexity)
    throw_failure( parameter => q{'iterator parameters' parameter must be a hashref} )
      unless Ref::Util::is_hashref( $in_ipar );
    throw_failure( parameter => q{'general parameters' parameter must be a hashref} )
      unless Ref::Util::is_hashref( $in_gpar );
    my %ipar = $in_ipar->%*;
    my %ipar_k;
    @ipar_k{ keys %ipar } = ();
    my %gpar = $in_gpar->%*;
    my %gpar_k;
    @gpar_k{ keys %gpar } = ();
    my $par;
    my @roles;
    my $class = $ipar{ +CLASS } // 'Iterator::Flex::Base';
    delete $ipar_k{ +CLASS };
    throw_failure( parameter => q{'class' parameter must be a string} )
      if Ref::Util::is_ref( $class );
    throw_failure( parameter => "can't load class $class" )
      if $class ne 'Iterator::Flex::Base'
      && !Module::Runtime::require_module( $class );
    delete $ipar_k{ +_NAME };
    throw_failure( parameter => "'@{[ _NAME ]}' parameter value must be a string\n" )
      if defined( $par = $ipar{ +_NAME } ) && Ref::Util::is_ref( $par );
    push @roles, 'State::Registry';
    delete $gpar_k{ +INPUT_EXHAUSTION };
    my $input_exhaustion = $gpar{ +INPUT_EXHAUSTION } // [ ( +RETURN ) => undef ];
    my @input_exhaustion
      = Ref::Util::is_arrayref( $input_exhaustion )
      ? ( $input_exhaustion->@* )
      : ( $input_exhaustion );
    delete $gpar_k{ +EXHAUSTION };
    my $has_output_exhaustion_policy = defined $gpar{ +EXHAUSTION };
    if ( $input_exhaustion[0] eq RETURN ) {
        push @roles, 'Exhaustion::ImportedReturn', 'Wrap::Return';
        push $input_exhaustion->@*, undef if @input_exhaustion == 1;
        $gpar{ +INPUT_EXHAUSTION } = \@input_exhaustion;
lib/Iterator/Flex/Factory.pm view on Meta::CPAN
    throw_failure( parameter => q{missing or undefined 'next' parameter} )
      if !defined( $ipar{ +NEXT } );
    for my $method ( NEXT, REWIND, RESET, PREV, CURRENT ) {
        delete $ipar_k{$method};
        next unless defined( my $code = $ipar{$method} );
        throw_failure( parameter => "'$method' parameter value must be a code reference\n" )
          unless Ref::Util::is_coderef( $code );
        # if $class can't perform the required method, add a role
        # which can.
        if ( $method eq NEXT ) {
            # next is always a closure, but the caller may want to
            # keep track of $self
            push @roles, defined $ipar{ +_SELF } ? 'Next::ClosedSelf' : 'Next::Closure';
            delete $ipar_k{ +_SELF };
        }
        else {
lib/Iterator/Flex/Factory.pm view on Meta::CPAN
    my ( $mpars, $ipars, $spars ) = parse_pars( $pars );
    my $action_on_failure = delete $mpars->{action_on_failure};
    throw_failure( parameter =>
          "unknown parameters pased to construct_from_iterable: @{[ join ', ', keys $mpars->%* ]}" )
      if $mpars->%*;
    ## no critic ( CascadingIfElse )
    if ( Ref::Util::is_blessed_ref( $obj ) ) {
        return construct_from_iterator_flex( $obj, $ipars, $spars )
          if $obj->isa( 'Iterator::Flex::Base' );
        return construct_from_object( $obj, $ipars, $spars );
    }
    elsif ( Ref::Util::is_arrayref( $obj ) ) {
        throw_failure(
            parameter => "unknown parameters pased to construct_from_iterable: @{[ join ', ', $ipars->%* ]}" )
          if $ipars->%*;
        require Iterator::Flex::Array;
        return Iterator::Flex::Array->new( $obj, $spars );
    }
    elsif ( Ref::Util::is_coderef( $obj ) ) {
        return construct( { $ipars->%*, next => $obj }, $spars );
    }
    elsif ( Ref::Util::is_globref( $obj ) ) {
        return construct( {
                $ipars->%*, next => sub { scalar <$obj> },
            },
            $spars,
        );
    }
    return undef
      if $action_on_failure eq RETURN;
lib/Iterator/Flex/Factory.pm view on Meta::CPAN
    my \@registry
      = exists $REGISTRY{ refaddr $obj }
      ? $REGISTRY{ refaddr $obj }[REG_GENERAL]
      : throw_failure( internal => q{non-registered Iterator::Flex iterator} );
    # if caller didn't specify an exhaustion, set it to return => undef
    my @want = do {
        my $exhaustion = $gpar->{ +EXHAUSTION } // [ ( +RETURN ) => undef ];
        Ref::Util::is_arrayref( $exhaustion )
          ? ( $exhaustion->@* )
          : ( $exhaustion );
    };
    # multiple different output exhaustion roles may have been
    # applied, so the object may claim to support both roles,
    # Exhaustion::Throw and Exhaustion::Return, although only the
    # latest one applied will work.  So, use what's in the registry to
    # figure out what it actually does.
lib/Iterator/Flex/Freeze.pm view on Meta::CPAN
use warnings;
use experimental 'signatures';
our $VERSION = '0.32';
use Iterator::Flex::Factory 'to_iterator';
use Iterator::Flex::Utils
  qw( RETURN EXHAUSTION :IterAttrs :ExhaustedMethods can_meth load_role throw_failure );
use parent 'Iterator::Flex::Base';
use Scalar::Util;
use Ref::Util;
use namespace::clean;
lib/Iterator/Flex/Freeze.pm view on Meta::CPAN
sub new ( $class, $code, $iterator, $pars = {} ) {
    throw_failure( parameter => q{'serialize' parameter is not a coderef} )
      unless Ref::Util::is_coderef( $code );
    throw_failure( parameter => "iterator (@{[ $iterator->_name ]}) must provide a freeze method" )
      unless can_meth( $iterator, FREEZE );
    throw_failure(
        parameter => "iterator (@{[ $iterator->_name ]}) must provide set_exhausted/is_exhausted methods" )
      unless can_meth( $iterator, SET_EXHAUSTED )
      && can_meth( $iterator, IS_EXHAUSTED );
    $class->SUPER::new( { serialize => $code, src => $iterator }, $pars );
}
sub construct ( $class, $state ) {
    throw_failure( parameter => q{'state' parameter must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    my ( $serialize, $src ) = @{$state}{qw( serialize src )};
    throw_failure( parameter => q{'serialize' must be a CODE reference} )
      unless Ref::Util::is_coderef( $serialize );
    # wrap the source iterator so that it returns undef on exhaustion.
    $src
      = to_iterator( $src, { ( +EXHAUSTION ) => RETURN } );
    my $self;
    my %params = (
        ( +_NAME ) => 'freeze',
        ( +_SELF ) => \$self,
lib/Iterator/Flex/Gather.pm view on Meta::CPAN
use v5.28;
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.32';
use Iterator::Flex::Factory 'to_iterator';
use Iterator::Flex::Utils qw[ THROW STATE EXHAUSTION :IterAttrs :IterStates ];
use Ref::Util;
use parent 'Iterator::Flex::Base';
use Iterator::Flex::Gather::Constants ':all';
use namespace::clean;
lib/Iterator/Flex/Gather.pm view on Meta::CPAN
sub new ( $class, $code, $iterable, $pars = {} ) {
    throw_failure( parameter => q{'code' parameter is not a coderef} )
      unless Ref::Util::is_coderef( $code );
    my %pars = $pars->%*;
    my %state = (
        code                => $code,
        cycle_on_exhaustion => delete( $pars{cycle_on_exhaustion} ) // GATHER_CYCLE_STOP,
        src                 => $iterable,
    );
    throw_failure( parameter => q{'cycle_on_exhaustion': illegal value} )
lib/Iterator/Flex/Gather.pm view on Meta::CPAN
      and $pars{cycle_on_exhaustion} != GATHER_CYCLE_CHOOSE
      and !$pars{cycle_on_exhaustion} & ( GATHER_CYCLE_STOP | GATHER_CYCLE_ABORT );
    $class->SUPER::new( \%state, \%pars );
}
sub construct ( $class, $state ) {
    throw_failure( parameter => q{'state' parameter must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    my ( $code, $src, $cycle_on_exhaustion ) = @{$state}{qw[ code src cycle_on_exhaustion ]};
    $src
      = to_iterator( $src, { ( +EXHAUSTION ) => THROW } );
    my $self;
    # cached value if current element should be in
    # next cycle
lib/Iterator/Flex/Gather.pm view on Meta::CPAN
                        $has_cache = !!1;
                    }
                    last if $cycle & ( GATHER_CYCLE_RESTART | GATHER_CYCLE_STOP | GATHER_CYCLE_ABORT );
                }
                1;
            };
            if ( !$ret && length $@ ) {
                die $@
                  unless Ref::Util::is_blessed_ref( $@ )
                  && $@->isa( 'Iterator::Flex::Failure::Exhausted' );
                local $_ = undef;
                my $result
                  = $cycle_on_exhaustion == GATHER_CYCLE_CHOOSE
                  ? $code->( \@gathered, GATHER_SRC_EXHAUSTED )
                  : $cycle_on_exhaustion;
                return $self->signal_exhaustion
                  if ( $result & GATHER_CYCLE_ABORT )
                  || ( $result & GATHER_CYCLE_STOP && !@gathered );
lib/Iterator/Flex/Grep.pm view on Meta::CPAN
use v5.28;
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.32';
use Iterator::Flex::Factory 'to_iterator';
use Iterator::Flex::Utils qw[ THROW STATE EXHAUSTION :IterAttrs :IterStates ];
use Ref::Util;
use parent 'Iterator::Flex::Base';
use namespace::clean;
lib/Iterator/Flex/Grep.pm view on Meta::CPAN
sub new ( $class, $code, $iterable, $pars = {} ) {
    throw_failure( parameter => q{'code' parameter is not a coderef} )
      unless Ref::Util::is_coderef( $code );
    $class->SUPER::new( { code => $code, src => $iterable }, $pars );
}
sub construct ( $class, $state ) {
    throw_failure( parameter => q{'state' parameter must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    my ( $code, $src ) = @{$state}{qw[ code src ]};
    $src
      = to_iterator( $src, { ( +EXHAUSTION ) => THROW } );
    my $self;
    my $iterator_state;
    return {
lib/Iterator/Flex/Grep.pm view on Meta::CPAN
            my $ret = eval {
                while ( 1 ) {
                    my $rv = $src->();
                    local $_ = $rv;
                    return $rv if $code->();
                }
                1;
            } or do {
                die $@
                  unless Ref::Util::is_blessed_ref( $@ )
                  && $@->isa( 'Iterator::Flex::Failure::Exhausted' );
                return $self->signal_exhaustion;
            };
            return $ret;
        },
        ( +RESET )    => sub { },
        ( +_DEPENDS ) => $src,
    };
}
lib/Iterator/Flex/Manual/Authoring.pod view on Meta::CPAN
The super class' constructor takes two arguments: a variable containing
iterator specific data (state), and the above-mentioned general
argument hash.  The state variable can take any form, it is not
interpreted by the C<Iterator::Flex> framework.
Here's the code for L<Iterator::Flex::Array/new>:
  sub new ( $class, $array, $pars={} ) {
      throw_failure( parameter => "argument must be an ARRAY reference" )
        unless Ref::Util::is_arrayref( $array );
      $class->SUPER::new( { array => $array }, $pars );
  }
It's pretty simple. It saves the general options hash if present,
stores the passed array (the state) in a hash, and passes both of
them to the super class' constructor.  (A hash is used here because
L<Iterator::Flex::Array> can be serialized, and extra state is
required to do so).
=head4 construct
lib/Iterator/Flex/Manual/Authoring.pod view on Meta::CPAN
  package My::Array;
  use strict;
  use warnings;
  use parent 'Iterator::Flex::Base';
  sub new {
      my $class = shift;
      my $gpar = Ref::Util::is_hashref( $_[-1] ) ? pop : {};
      throw_failure( parameter => "argument must be an ARRAY reference" )
        unless Ref::Util::is_arrayref( $_[0] );
      $class->SUPER::new( { array => $_[0] }, $gpar );
  }
  sub construct {
     my ( $class, $state ) = @_;
     # initialize lexical variables here
     ...
     my $arr = $state->{array};
lib/Iterator/Flex/Map.pm view on Meta::CPAN
use v5.28;
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.32';
use Iterator::Flex::Utils qw( STATE THROW EXHAUSTION :IterAttrs :IterStates );
use Iterator::Flex::Factory 'to_iterator';
use Ref::Util;
use parent 'Iterator::Flex::Base';
use namespace::clean;
lib/Iterator/Flex/Map.pm view on Meta::CPAN
sub new ( $class, $code, $iterable, $pars = {} ) {
    throw_failure( parameter => q{'code' parameter is not a coderef} )
      unless Ref::Util::is_coderef( $code );
    $class->SUPER::new( { code => $code, src => $iterable }, $pars );
}
sub construct ( $class, $state ) {
    throw_failure( parameter => q{'state' parameter must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    my ( $code, $src ) = @{$state}{qw[ code src ]};
    $src
      = to_iterator( $src, { ( +EXHAUSTION ) => THROW } );
    my @values;
    my $self;
    my $iterator_state;
lib/Iterator/Flex/Map.pm view on Meta::CPAN
            return $self->signal_exhaustion if $iterator_state == IterState_EXHAUSTED;
            unless ( @values ) {
                eval {
                    my $value = $src->();
                    local $_ = $value;
                    @values = $code->();
                    1;
                } or do {
                    die $@
                      unless Ref::Util::is_blessed_ref( $@ )
                      && $@->isa( 'Iterator::Flex::Failure::Exhausted' );
                    return $self->signal_exhaustion;
                };
            }
            return shift @values;
        },
        ( +RESET )    => sub { @values = () },
        ( +REWIND )   => sub { @values = () },
        ( +_DEPENDS ) => $src,
lib/Iterator/Flex/Product.pm view on Meta::CPAN
use v5.28;
use strict;
use warnings;
use experimental qw( signatures declared_refs refaliasing );
our $VERSION = '0.32';
use Iterator::Flex::Utils qw( RETURN STATE EXHAUSTION :IterAttrs :IterStates can_meth );
use Iterator::Flex::Factory 'to_iterator';
use parent 'Iterator::Flex::Base';
use Ref::Util;
use List::Util;
use namespace::clean;
lib/Iterator/Flex/Product.pm view on Meta::CPAN
sub new ( $class, @args ) {
    my $pars = Ref::Util::is_hashref( $args[-1] ) ? pop @args : {};
    throw_failure( parameter => 'not enough parameters' )
      unless @args;
    my @iterators;
    my @keys;
    # distinguish between ( key => iterator, key =>iterator ) and ( iterator, iterator );
    if ( Ref::Util::is_ref( $args[0] ) ) {
        @iterators = @args;
    }
    else {
        throw_failure( parameter => 'expected an even number of arguments' )
          if @args % 2;
        while ( @args ) {
            push @keys,      shift @args;
            push @iterators, shift @args;
        }
    }
    $class->SUPER::new( { keys => \@keys, depends => \@iterators, value => [] }, $pars );
}
sub construct ( $class, $state ) {    ## no critic (ExcessComplexity)
    throw_failure( parameter => q{state must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );
    $state->{value} //= [];
    my ( \@depends, \@keys, \@value, $thaw )
      = @{$state}{qw[ depends keys value thaw ]};
    # transform into iterators if required.
    my @iterators
      = map { to_iterator( $_, { ( +EXHAUSTION ) => RETURN } ) } @depends;
lib/Iterator/Flex/Role/Error/Throw.pm view on Meta::CPAN
# ABSTRACT: signal error by throwing
use v5.28;
use strict;
use warnings;
our $VERSION = '0.32';
use Iterator::Flex::Utils qw( :default REG_GENERAL REG_GP_ERROR  );
use Ref::Util;
use Role::Tiny;
use experimental 'signatures';
use namespace::clean;
lib/Iterator/Flex/Role/Error/Throw.pm view on Meta::CPAN
sub signal_error ( $self, $message = undef ) {
    $self->set_error;
    my $exception = $REGISTRY{ refaddr $self }[REG_GENERAL][REG_GP_ERROR][1];
    my @message = ( $message // () );
    $exception->( @message ) if Ref::Util::is_coderef( $exception );
    require Iterator::Flex::Failure;
    Iterator::Flex::Failure::Error->throw( @message );
}
1;
#
# This file is part of Iterator-Flex
lib/Iterator/Flex/Role/Exhaustion/Throw.pm view on Meta::CPAN
package Iterator::Flex::Role::Exhaustion::Throw;
# ABSTRACT: signal exhaustion by setting exhausted flag;
use v5.28;
use strict;
use warnings;
our $VERSION = '0.32';
use Ref::Util;
use Iterator::Flex::Utils qw( :default REG_GENERAL REG_GP_EXHAUSTION );
use Role::Tiny;
use experimental 'signatures';
use namespace::clean;
lib/Iterator/Flex/Role/Exhaustion/Throw.pm view on Meta::CPAN
sub signal_exhaustion ( $self, @ ) {
    $self->set_exhausted;
    my $exception = $REGISTRY{ refaddr $self }[REG_GENERAL][REG_GP_EXHAUSTION][1];
    $exception->() if Ref::Util::is_coderef( $exception );
    require Iterator::Flex::Failure;
    Iterator::Flex::Failure::Exhausted->throw;
}
1;
#
# This file is part of Iterator-Flex
lib/Iterator/Flex/Role/Next/ClosedSelf.pm view on Meta::CPAN
package Iterator::Flex::Role::Next::ClosedSelf;
# ABSTRACT: Role for closure iterator which closes over self
use v5.28;
use strict;
use warnings;
our $VERSION = '0.32';
use Ref::Util;
use Scalar::Util;
use Iterator::Flex::Utils qw( NEXT _SELF );
use Role::Tiny;
use experimental 'signatures';
use namespace::clean;
lib/Iterator/Flex/Role/Wrap/Throw.pm view on Meta::CPAN
# ABSTRACT: Role to add throw on exhaustion to an iterator which adapts another iterator
use v5.28;
use strict;
use warnings;
our $VERSION = '0.32';
use List::Util 'first';
use Iterator::Flex::Utils qw( INPUT_EXHAUSTION PASSTHROUGH );
use Ref::Util             qw( is_ref is_blessed_ref is_regexpref is_arrayref is_coderef );
use Role::Tiny;
use experimental 'signatures';
use namespace::clean;
around _construct_next => sub ( $orig, $class, $ipar, $gpar ) {
    my $next = $class->$orig( $ipar, $gpar );
    my $exception = (
lib/Iterator/Flex/Sequence.pm view on Meta::CPAN
sub new ( $class, @args ) {
    my $pars = Ref::Util::is_hashref( $args[-1] ) ? pop @args : {};
    throw_failure( parameter => q{incorrect number of arguments for sequence} )
      if @args < 1 || @args > 3;
    my %state;
    $state{step}  = pop @args if @args == 3;
    $state{end}   = pop @args;
    $state{begin} = pop @args;
lib/Iterator/Flex/Stack.pm view on Meta::CPAN
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;
lib/Iterator/Flex/Utils.pm view on Meta::CPAN
use v5.28;
use strict;
use warnings;
use experimental 'signatures', 'postderef';
our $VERSION = '0.32';
use Scalar::Util qw( refaddr );
use Ref::Util    qw( is_hashref );
use Exporter 'import';
use experimental 'declared_refs';
our %REGISTRY;
sub mk_indices {
    my $idx = 0;
    return { map { $_ => $idx++ } @_ };
}
lib/Iterator/Flex/Utils.pm view on Meta::CPAN
sub can_meth ( $obj, @methods ) {
    my $par = Ref::Util::is_hashref( $methods[-1] ) ? pop @methods : {};
    for my $method ( @methods ) {
        throw_failure( parameter => q{'method' parameters must be a string} )
          if Ref::Util::is_ref( $method );
        my $sub;
        foreach ( "__${method}__", $method ) {
            if ( defined( $sub = $obj->can( $_ ) ) ) {
                my @ret = ( ( !!$par->{name} ? $_ : () ), ( !!$par->{code} ? $sub : () ) );
                push @ret, $sub unless @ret;
                return @ret > 1 ? @ret : $ret[0];
            }
        }
    }
lib/Iterator/Flex/Utils.pm view on Meta::CPAN
sub resolve_meth ( $target, $method, @fallbacks ) {
    my $code = do {
        if ( defined $method ) {
            Ref::Util::is_coderef( $method )
              ? $method
              : $target->can( $method )
              // throw_failure( parameter => qq{method '$method' is not provided by the object} );
        }
        else {
            can_meth( $target, @fallbacks );
        }
    };
lib/Iterator/Flex/Zip.pm view on Meta::CPAN
use v5.28;
use strict;
use warnings;
use experimental 'signatures', 'declared_refs';
our $VERSION = '0.32';
use Iterator::Flex::Factory 'to_iterator';
use Iterator::Flex::Utils qw[ THROW STATE EXHAUSTION :IterAttrs :IterStates throw_failure ];
use Ref::Util 'is_ref', 'is_hashref', 'is_blessed_ref';
use List::Util 'first';
use parent 'Iterator::Flex::Base';
use constant { map { $_ => lc } qw( ON_EXHAUSTION TRUNCATE THROW INSERT ) };
use namespace::clean;
t/00-report-prereqs.dd view on Meta::CPAN
                                      'Test::Spelling' => '0.17',
                                      'Test::Version' => '1'
                                    }
                    },
       'runtime' => {
                      'requires' => {
                                      'Class::Method::Modifiers' => '0',
                                      'List::Util' => '1.33',
                                      'Module::Runtime' => '0',
                                      'Package::Variant' => '0',
                                      'Ref::Util' => '0',
                                      'Role::Tiny' => '2.002004',
                                      'custom::failures' => '0',
                                      'experimental' => '0',
                                      'namespace::clean' => '0',
                                      'perl' => 'v5.28.0'
                                    }
                    },
       'test' => {
                   'recommends' => {
                                     'CPAN::Meta' => '2.120900'
t/Common/iterator.t view on Meta::CPAN
#! perl
use v5.28;
use Test2::V0;
use Scalar::Util 'refaddr';
use Ref::Util 'is_ref';
use Iterator::Flex::Common 'iterator';
sub use_object {
    sub { $_[0]->next }
}
sub use_coderef {
    sub { $_[0]->() }
}
sub test {