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.29'
Iterator::Flex::Zip:
file: lib/Iterator/Flex/Zip.pm
version: '0.29'
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.29'
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
package Iterator::Flex::Array;
# ABSTRACT: Array Iterator Class
use strict;
use warnings;
our $VERSION = '0.29';
use Iterator::Flex::Utils ':IterAttrs';
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 = {} ) {
$class->_throw( parameter => 'argument must be an ARRAY reference' )
unless Ref::Util::is_arrayref( $array );
$class->SUPER::new( { array => $array }, $pars );
}
sub construct ( $class, $state ) {
$class->_throw( 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 ]};
$class->_throw( parameter => q{state 'array' parameter must be a HASH reference} )
unless Ref::Util::is_arrayref( $arr );
my $len = @$arr;
$next = 0 unless defined $next;
$class->_throw( parameter => q{illegal value for state 'prev' argument} )
if defined $prev && ( $prev < 0 || $prev >= $len );
$class->_throw( parameter => q{illegal value for state 'current' argument} )
if defined $current && ( $current < 0 || $current >= $len );
lib/Iterator/Flex/ArrayLike.pm view on Meta::CPAN
package Iterator::Flex::ArrayLike;
# ABSTRACT: ArrayLike Iterator Class
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.29';
use Ref::Util;
use Iterator::Flex::Utils ':IterAttrs';
use namespace::clean;
use parent 'Iterator::Flex::Base';
use Role::Tiny::With ();
Role::Tiny::With::with 'Iterator::Flex::Role::Utils';
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 ) {
$class->_throw( 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 ]};
$class->_throw( parameter => q{state 'object' argument must be a blessed reference} )
unless Ref::Util::is_blessed_ref( $obj );
$length = $class->_resolve_meth( $obj, $length, 'length', 'len' );
$at = $class->_resolve_meth( $obj, $at, 'at', 'getitem' );
my $len = $obj->$length;
$next = 0 unless defined $next;
$class->_throw( parameter => q{illegal value for state 'prev' argument} )
lib/Iterator/Flex/Base.pm view on Meta::CPAN
use 5.10.0;
use strict;
use warnings;
use experimental qw( signatures postderef declared_refs );
our $VERSION = '0.29';
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', 'Iterator::Flex::Role::Utils';
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 {
$class->_throw( 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 {
$class->_throw( parameter => "unknown exhaustion action: $exhaustion_action[0]" );
}
if ( defined( my $par = $ipar{ +METHODS } ) ) {
require Iterator::Flex::Method;
$class->_throw( 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};
$class->_throw( 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 { $class->_load_role( $_ ) } @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->%*;
$class->_throw( parameter => "unknown interface parameters: @{[ join ', ', @bad ]}" )
if @bad;
$class->_throw( 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 );
$class->_throw( 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.29';
use parent 'Iterator::Flex::Base';
use Iterator::Flex::Utils qw( STATE :IterAttrs :IterStates throw_failure );
use Iterator::Flex::Factory;
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 => [ Iterator::Flex::Factory->to_iterator( $iterable ) ],
},
\%pars
lib/Iterator/Flex/Cache.pm view on Meta::CPAN
sub construct ( $class, $state ) {
$class->_throw( 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 $iterator_state;
return {
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 $class->_throw( parameter => 'not enough parameters' );
$class->SUPER::new( {
depends => \@args,
current_iterator_index => undef,
},
$pars
);
}
sub construct ( $class, $state ) {
$class->_throw( parameter => q{state must be a HASH reference} )
unless Ref::Util::is_hashref( $state );
$state->{value} //= [];
my ( \@depends, $current_iterator_index, $prev, $current, $next, undef )
= @{$state}{ 'depends', 'current_iterator_index', 'prev', 'current', 'next', 'thaw' };
# transform into iterators if required.
my @iterators
= map { Iterator::Flex::Factory->to_iterator( $_, { ( +EXHAUSTION ) => RETURN } ) } @depends;
lib/Iterator/Flex/Chunk.pm view on Meta::CPAN
# ABSTRACT: Chunk Iterator Class
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.29';
use Iterator::Flex::Factory;
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 ) {
$class->_throw( parameter => q{'state' parameter must be a HASH reference} )
unless Ref::Util::is_hashref( $state );
my ( $src, $capacity ) = @{$state}{qw[ src capacity ]};
$src
= Iterator::Flex::Factory->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
return $self->signal_exhaustion
if $iterator_state == IterState_EXHAUSTED || $next_is_exhausted;
my @chunked;
my $ret = eval {
push @chunked, $src->() while @chunked < $capacity;
1;
};
if ( !$ret && length $@ ) {
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
use Exporter 'import';
our @EXPORT_OK = qw[
iterator iter iarray icycle icache
icat ichain ichunk igather igrep imap iproduct iseq istack 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;
lib/Iterator/Flex/Cycle.pm view on Meta::CPAN
# ABSTRACT: Array Cycle Iterator Class
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.29';
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, $ ) {
$class->_throw( parameter => q{argument must be an ARRAY reference} )
unless Ref::Util::is_arrayref( $array );
$class->SUPER::new( { array => $array }, {} );
}
sub construct ( $class, $state ) {
$class->_throw( 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;
$class->_throw( 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 5.25.0;
use strict;
use warnings;
use experimental qw( signatures declared_refs refaliasing);
our $VERSION = '0.29';
use Ref::Util ();
use Role::Tiny ();
use Role::Tiny::With ();
use Module::Runtime;
use Iterator::Flex::Base;
use Iterator::Flex::Utils qw[
:ExhaustionActions
:default
:RegistryIndices
lib/Iterator/Flex/Factory.pm view on Meta::CPAN
sub construct ( $CLASS, $in_ipar = {}, $in_gpar = {} ) { ## no critic (ExcessComplexity)
$CLASS->_throw( parameter => q{'iterator parameters' parameter must be a hashref} )
unless Ref::Util::is_hashref( $in_ipar );
$CLASS->_throw( 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 };
$CLASS->_throw( parameter => q{'class' parameter must be a string} )
if Ref::Util::is_ref( $class );
$CLASS->_throw( parameter => "can't load class $class" )
if $class ne 'Iterator::Flex::Base'
&& !Module::Runtime::require_module( $class );
delete $ipar_k{ +_NAME };
$CLASS->_throw( 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
$CLASS->_throw( 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} );
$CLASS->_throw( 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
sub construct_from_iterable ( $CLASS, $obj, $pars = {} ) {
my ( $mpars, $ipars, $spars ) = parse_pars( $pars );
$CLASS->_throw( parameter =>
"unknown parameters pased to construct_from_iterable: @{[ join ', ', keys $mpars->%* ]}" )
if $mpars->%*;
## no critic ( CascadingIfElse )
if ( Ref::Util::is_blessed_ref( $obj ) ) {
return $CLASS->construct_from_object( $obj, $ipars, $spars );
}
elsif ( Ref::Util::is_arrayref( $obj ) ) {
$CLASS->_throw(
parameter => "unknown parameters pased to construct_from_iterable: @{[ join ', ', $ipars->%* ]}" )
if $ipars->%*;
return $CLASS->construct_from_array( $obj, $spars );
}
elsif ( Ref::Util::is_coderef( $obj ) ) {
return $CLASS->construct( { $ipars->%*, next => $obj }, $spars );
}
elsif ( Ref::Util::is_globref( $obj ) ) {
return $CLASS->construct( {
$ipars->%*, next => sub { scalar <$obj> }
},
$spars
);
}
$CLASS->_throw(
parameter => sprintf q{'%s' object is not iterable},
( ref( $obj ) || 'SCALAR' ) );
lib/Iterator/Flex/Factory.pm view on Meta::CPAN
sub construct_from_object ( $CLASS, $obj, $ipar, $gpar ) {
$CLASS->_throw( parameter => q['$object' parameter is not a real object] )
unless Ref::Util::is_blessed_ref( $obj );
return construct_from_iterator_flex( $CLASS, $obj, $ipar, $gpar )
if $obj->isa( 'Iterator::Flex::Base' );
my %ipar = $ipar->%*;
my %gpar = $gpar->%*;
$gpar{ +INPUT_EXHAUSTION } //= [ ( +RETURN ) => undef ];
if ( !exists $ipar{ +NEXT } ) {
lib/Iterator/Flex/Factory.pm view on Meta::CPAN
my \@registry
= exists $REGISTRY{ refaddr $obj }
? $REGISTRY{ refaddr $obj }[REG_GENERAL]
: $CLASS->_throw( 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 strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.29';
use Iterator::Flex::Factory;
use Iterator::Flex::Utils qw( RETURN EXHAUSTION :IterAttrs :ExhaustedMethods );
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 = {} ) {
$class->_throw( parameter => q{'serialize' parameter is not a coderef} )
unless Ref::Util::is_coderef( $code );
$class->_throw( parameter => "iterator (@{[ $iterator->_name ]}) must provide a freeze method" )
unless $class->_can_meth( $iterator, FREEZE );
$class->_throw(
parameter => "iterator (@{[ $iterator->_name ]}) must provide set_exhausted/is_exhausted methods" )
unless $class->_can_meth( $iterator, SET_EXHAUSTED )
&& $class->_can_meth( $iterator, IS_EXHAUSTED );
$class->SUPER::new( { serialize => $code, src => $iterator }, $pars );
}
sub construct ( $class, $state ) {
$class->_throw( parameter => q{'state' parameter must be a HASH reference} )
unless Ref::Util::is_hashref( $state );
my ( $serialize, $src ) = @{$state}{qw( serialize src )};
$class->_throw( 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
= Iterator::Flex::Factory->to_iterator( $src, { ( +EXHAUSTION ) => RETURN } );
my $self;
my %params = (
( +_NAME ) => 'freeze',
( +_SELF ) => \$self,
lib/Iterator/Flex/Gather.pm view on Meta::CPAN
# ABSTRACT: Gather Iterator Class
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.29';
use Iterator::Flex::Factory;
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 = {} ) {
$class->_throw( 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,
);
$class->_throw( 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 ) {
$class->_throw( 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
= Iterator::Flex::Factory->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
# ABSTRACT: Grep Iterator Class
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.29';
use Iterator::Flex::Factory;
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 = {} ) {
$class->_throw( 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 ) {
$class->_throw( parameter => q{'state' parameter must be a HASH reference} )
unless Ref::Util::is_hashref( $state );
my ( $code, $src ) = @{$state}{qw[ code src ]};
$src
= Iterator::Flex::Factory->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->();
}
};
if ( $@ ne q{} ) {
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={} ) {
$class->_throw( 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 : {};
$class->_throw( 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
# ABSTRACT: Map Iterator Class
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.29';
use Iterator::Flex::Utils qw( STATE THROW EXHAUSTION :IterAttrs :IterStates );
use Iterator::Flex::Factory;
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 = {} ) {
$class->_throw( 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 ) {
$class->_throw( parameter => q{'state' parameter must be a HASH reference} )
unless Ref::Util::is_hashref( $state );
my ( $code, $src ) = @{$state}{qw[ code src ]};
$src
= Iterator::Flex::Factory->to_iterator( $src, { ( +EXHAUSTION ) => THROW } );
my @values;
my $self;
my $iterator_state;
lib/Iterator/Flex/Map.pm view on Meta::CPAN
## no critic( Until )
until ( @values ) {
@values = eval {
my $value = $src->();
local $_ = $value;
$code->();
};
if ( $@ ne q{} ) {
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 strict;
use warnings;
use experimental qw( signatures declared_refs refaliasing );
our $VERSION = '0.29';
use Iterator::Flex::Utils qw( RETURN STATE EXHAUSTION :IterAttrs :IterStates );
use Iterator::Flex::Factory;
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 : {};
$class->_throw( 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 {
$class->_throw( 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)
$class->_throw( 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 { Iterator::Flex::Factory->to_iterator( $_, { ( +EXHAUSTION ) => RETURN } ) } @depends;
lib/Iterator/Flex/Role/Error/Throw.pm view on Meta::CPAN
package Iterator::Flex::Role::Error::Throw;
# ABSTRACT: signal error by throwing
use strict;
use warnings;
our $VERSION = '0.29';
use Iterator::Flex::Utils qw( :default REG_GENERAL REG_GP_ERROR );
use Ref::Util;
use Role::Tiny;
use experimental 'signatures';
use namespace::clean;
sub signal_error ( $self ) {
$self->set_error;
my $exception = $REGISTRY{ refaddr $self }[REG_GENERAL][REG_GP_ERROR][1];
$exception->() if Ref::Util::is_coderef( $exception );
require Iterator::Flex::Failure;
Iterator::Flex::Failure::Error->throw;
}
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 strict;
use warnings;
our $VERSION = '0.29';
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 strict;
use warnings;
our $VERSION = '0.29';
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/Utils.pm view on Meta::CPAN
package Iterator::Flex::Role::Utils;
# ABSTRACT: Role based utilities
use strict;
use warnings;
our $VERSION = '0.29';
use Ref::Util;
use Role::Tiny;
use experimental 'signatures';
lib/Iterator/Flex/Role/Utils.pm view on Meta::CPAN
sub _can_meth ( $self, @methods ) {
my $thing = Ref::Util::is_blessed_ref( $methods[0] ) ? shift @methods : $self;
my $par = Ref::Util::is_hashref( $methods[-1] ) ? pop @methods : {};
for my $method ( @methods ) {
$self->_throw( parameter => q{'method' parameters must be a string} )
if Ref::Util::is_ref( $method );
my $sub;
foreach ( "__${method}__", $method ) {
if ( defined( $sub = $thing->can( $_ ) ) ) {
my @ret = ( ( !!$par->{name} ? $_ : () ), ( !!$par->{code} ? $sub : () ) );
push @ret, $sub unless @ret;
return @ret > 1 ? @ret : $ret[0];
}
}
}
lib/Iterator/Flex/Role/Utils.pm view on Meta::CPAN
sub _resolve_meth ( $obj, $target, $method, @fallbacks ) {
my $code = do {
if ( defined $method ) {
Ref::Util::is_coderef( $method )
? $method
: $target->can( $method )
// $obj->_throw( parameter => qq{method '$method' is not provided by the object} );
}
else {
$obj->_can_meth( $target, @fallbacks );
}
};
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 strict;
use warnings;
our $VERSION = '0.29';
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 : {};
$class->_throw( 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 ) {
$class->_throw( 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 { Iterator::Flex::Factory->to_iterator( $_, { ( +EXHAUSTION ) => RETURN } ) } @depends;
my @snapshot = @stack;
lib/Iterator/Flex/Utils.pm view on Meta::CPAN
use 5.28.0; # hash slices
use strict;
use warnings;
use experimental 'signatures', 'postderef';
our $VERSION = '0.29';
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/Zip.pm view on Meta::CPAN
# ABSTRACT: Zip Iterator Class
use strict;
use warnings;
use experimental 'signatures', 'declared_refs';
our $VERSION = '0.29';
use Iterator::Flex::Factory;
use Iterator::Flex::Utils qw[ THROW STATE EXHAUSTION :IterAttrs :IterStates ];
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 strict;
use warnings;
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 {