Skip to content

Commit

Permalink
Use iterators to handle take_while/skip_while/concat instead of using…
Browse files Browse the repository at this point in the history
… element_at, thus avoiding needing to deal with exception handling.
  • Loading branch information
tobyink committed Apr 7, 2021
1 parent 2eb321c commit c2da9ba
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 51 deletions.
87 changes: 39 additions & 48 deletions lib/LINQ/Collection.pm
Original file line number Diff line number Diff line change
Expand Up @@ -190,27 +190,17 @@ sub take_while {
my $self = shift;
my $filter = LINQ::Util::Internal::assert_code( @_ );
my $stopped = 0;
my $idx = 0;
my $iter = $self->to_iterator;

require LINQ;
require LINQ::Iterator;
'LINQ::Iterator'->new( sub {
local ( $@, $_ );
my $next;
my $ok = eval { $next = $self->element_at( $idx ); not $stopped };
my $e = $@;
if ( $ok and $filter->( $_ = $next ) ) {
++$idx;
return $next;
}
if ( defined $e and not $ok ) {
require Scalar::Util;
die( $e ) unless Scalar::Util::blessed( $e );
die( $e ) unless $e->isa( 'LINQ::Exception::NotFound' );
die( $e ) unless $e->collection == $self;
LINQ::Util::Internal::create_linq( sub {
return LINQ::END() if $stopped;
my @got = $iter->();
if ( ! @got or ! $filter->( $_ = $got[0] ) ) {
$stopped++;
return LINQ::END();
}
$stopped = 1;
return LINQ::END();
return $got[0];
} );
} #/ sub take_while

Expand All @@ -221,46 +211,47 @@ sub skip {
}

sub skip_while {
my $self = shift;
my $filter = LINQ::Util::Internal::assert_code( @_ );
my $skipping = 1;
$self->where(
sub {
$skipping = 0
if $skipping
&& !$filter->( $_ );
not $skipping;
}
);
my $self = shift;
my $filter = LINQ::Util::Internal::assert_code( @_ );
my $stopped = 0;
my $started = 0;
my $iter = $self->to_iterator;

require LINQ;
LINQ::Util::Internal::create_linq( sub {
SKIPPING: {
return LINQ::END() if $stopped;
my @got = $iter->();
if ( ! @got ) {
$stopped++;
redo SKIPPING;
}
return $got[0] if $started;
if ( $filter->( $_ = $got[0] ) ) {
redo SKIPPING;
}
++$started;
return $got[0];
};
} );
} #/ sub skip_while

sub concat {
my @collections = @_;
my @collections = map $_->to_iterator, @_;
my $idx = 0;

require LINQ;
require LINQ::Iterator;
'LINQ::Iterator'->new( sub {
local ( $@, $_ );
my $next;
LINQ::Util::Internal::create_linq( sub {
FIND_NEXT: {
return LINQ::END() if not @collections;

my $ok = eval { $next = $collections[0]->element_at( $idx ); 1 };
my $e = $@;
if ( $ok ) {
++$idx;
return $next;
my @got = $collections[0]->();
if ( not @got ) {
shift @collections;
redo FIND_NEXT;
}
elsif ( defined $e and not $ok ) {
require Scalar::Util;
die( $e ) unless Scalar::Util::blessed( $e );
die( $e ) unless $e->isa( 'LINQ::Exception::NotFound' );
die( $e ) unless $e->collection == $collections[0];
}
shift @collections;
$idx = 0;
redo FIND_NEXT;

return $got[0];
};
} );
}
Expand Down
4 changes: 1 addition & 3 deletions t/21iter-take_while.t
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
Given an iterator LINQ, checks exceptions get rethrown correctly.
Test fails on older Perls for... reasons(?) so we skip test on Perl < 5.16.
=head1 AUTHOR
Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
Expand All @@ -23,7 +21,7 @@ the same terms as the Perl 5 programming language system itself.

BEGIN { $LINQ::FORCE_ITERATOR = 1 }

use Test::Modern -requires => { 'perl' => '5.016' };
use Test::Modern;
use LINQ qw( LINQ );

my $c1 = LINQ( sub { die "My error" } )->take_while( sub { 1 } );
Expand Down

0 comments on commit c2da9ba

Please sign in to comment.