view release on metacpan or search on metacpan
"Test::Spelling" : "0.12",
"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/Stack.pm
version: '0.19'
Iterator::Flex::Utils:
file: lib/Iterator/Flex/Utils.pm
version: '0.19'
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.19'
x_generated_by_perl: v5.40.0
; --- 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.19';
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 => "'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 => "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 => "illegal value for state 'prev' argument" )
if defined $prev && ( $prev < 0 || $prev >= $len );
$class->_throw( parameter => "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.19';
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 => "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 => "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 => "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 => "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 );
our $VERSION = '0.19';
use Ref::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
:ExhaustionActions
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( "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 => "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 '' ) {
my $error = $@;
die $error
unless Ref::Util::is_blessed_ref( $error )
&& $error->isa( 'Iterator::Flex::Failure::RoleExists' );
$role = $error->payload;
}
push @roles, '+' . $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
}
sub _validate_interface_pars ( $class, $pars ) {
my @bad = check_invalid_interface_parameters( [ 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 ) {
my @bad = check_invalid_signal_parameters( [ 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/Cache.pm view on Meta::CPAN
use strict;
use warnings;
use experimental qw( signatures postderef );
our $VERSION = '0.19';
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 => '"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 => "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 => "state must be a HASH reference" )
unless Ref::Util::is_hashref( $state );
$state->{value} //= [];
my ( \@depends, $current_iterator_index, $prev, $current, $next, $thaw )
= @{$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;
my $value;
lib/Iterator/Flex/Common.pm view on Meta::CPAN
use Exporter 'import';
our @EXPORT_OK = qw[
iterator iter iarray icycle icache
icat igrep imap iproduct iseq istack ifreeze 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.19';
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 => "argument must be an ARRAY reference" )
unless Ref::Util::is_arrayref( $array );
$class->SUPER::new( { array => $array }, {} );
}
sub construct ( $class, $state ) {
$class->_throw( parameter => "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 => "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.19';
use Ref::Util ();
use Role::Tiny ();
use Role::Tiny::With ();
use Module::Runtime;
use Iterator::Flex::Base;
use Iterator::Flex::Utils qw[
:ExhaustionActions
:default
:RegistryKeys
lib/Iterator/Flex/Factory.pm view on Meta::CPAN
sub construct ( $CLASS, $in_ipar = {}, $in_gpar = {} ) {
$CLASS->_throw( parameter => "'iterator parameters' parameter must be a hashref" )
unless Ref::Util::is_hashref( $in_ipar );
$CLASS->_throw( parameter => "'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 => "'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 => "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->%*;
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 "'%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 }{ +GENERAL }
: $CLASS->_throw( internal => "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.19';
use Iterator::Flex::Factory;
use Iterator::Flex::Utils qw( RETURN EXHAUSTION :IterAttrs :Methods );
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 => "'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 => "'state' parameter must be a HASH reference" )
unless Ref::Util::is_hashref( $state );
my ( $serialize, $src ) = @{$state}{qw( serialize src )};
$class->_throw( parameter => "'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/Grep.pm view on Meta::CPAN
# ABSTRACT: Grep Iterator Class
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.19';
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 => "'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 => "'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 {
foreach ( ; ; ) {
my $rv = $src->();
local $_ = $rv;
return $rv if $code->();
}
};
if ( $@ ne '' ) {
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.19';
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 => "'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 => "'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/Map.pm view on Meta::CPAN
( +NEXT ) => sub {
return $self->signal_exhaustion if $iterator_state == +IterState_EXHAUSTED;
my $ret = eval {
my $value = $src->();
local $_ = $value;
$code->();
};
if ( $@ ne '' ) {
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/Product.pm view on Meta::CPAN
use strict;
use warnings;
use experimental qw( signatures declared_refs refaliasing );
our $VERSION = '0.19';
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 ) {
$class->_throw( parameter => "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.19';
use Iterator::Flex::Utils qw( :default :RegistryKeys );
use Ref::Util;
use Role::Tiny;
use experimental 'signatures';
use namespace::clean;
sub signal_error ( $self ) {
$self->set_error;
my $exception = $REGISTRY{ refaddr $self }{ +GENERAL }{ +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.19';
use Ref::Util;
use Iterator::Flex::Utils qw( :default :RegistryKeys );
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 }{ +GENERAL }{ +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.19';
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.19';
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 => "'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
package Iterator::Flex::Role::Wrap::Throw;
# ABSTRACT: Role to add throw on exhaustion to an iterator which adapts another iterator
use strict;
use warnings;
our $VERSION = '0.19';
use Iterator::Flex::Utils qw( :RegistryKeys 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 => "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 => "state must be a HASH reference" )
unless Ref::Util::is_hashref( $state );
$state->{value} //= [];
my ( \@depends, $prev, $current, $next, $thaw )
= @{$state}{ 'depends', 'prev', 'current', 'next', 'thaw' };
# transform into iterators if required.
my @stack
= map { Iterator::Flex::Factory->to_iterator( $_, { ( +EXHAUSTION ) => +RETURN } ) } @depends;
my $value;
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.19';
use Scalar::Util qw( refaddr );
use Ref::Util qw( is_hashref );
use Exporter 'import';
our %REGISTRY;
our %ExhaustionActions;
our %RegistryKeys;
our %IterAttrs;
our %Methods;
our %IterStates;
t/00-report-prereqs.dd view on Meta::CPAN
'Test::Spelling' => '0.12',
'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 {