Acme-IEnumerable
view release on metacpan or search on metacpan
lib/Acme/IEnumerable.pm view on Meta::CPAN
# ...
}
return _create sub {
return sub {
state $counter = $from // 0;
return \($counter++);
};
};
}
sub take {
my ($self, $count) = @_;
return _create sub {
return sub {
state $left = $count;
return unless $left;
$left--;
state $base = $self->new();
my $item = $base->();
return unless ref $item;
return $item;
};
};
}
sub take_until {
my ($self, $predicate) = @_;
return $self->take_while(sub {
!$predicate->($_);
});
}
sub take_while {
my ($self, $predicate) = @_;
return _create sub {
return sub {
state $base = $self->new();
my $item = $base->();
return unless ref $item;
local $_ = $$item;
return unless $predicate->($_);
return $item;
};
};
}
sub group_by {
my ($self, $key_extractor) = @_;
return _create sub {
my $base = $self->new;
my %temp;
while (1) {
my $item = $base->();
last unless ref $item;
local $_ = $$item;
my $key = $key_extractor->($_);
push @{ $temp{$key} }, $_;
}
my @temp = map {
Acme::IEnumerable::Grouping->from_list($_, @{$temp{$_}})
} keys %temp;
return Acme::IEnumerable->from_list(@temp)->new;
};
}
sub stack_by {
my ($self, $key_extractor) = @_;
return _create sub {
# TODO: make this more lazy?
my $base = $self->new;
my @list;
while (1) {
my $item = $base->();
last unless ref $item;
local $_ = $$item;
my $key = $key_extractor->($_);
if (not @list or $key ne $list[-1]->{key}) {
push @list, {
key => $key,
};
}
push @{ $list[-1]->{value} }, $_;
}
my @temp = map {
Acme::IEnumerable::Grouping->from_list($_->{key}, @{ $_->{value} })
} @list;
return Acme::IEnumerable->from_list(@temp)->new;
};
}
sub skip {
my ($self, $count) = @_;
return _create sub {
return sub {
state $base = $self->new();
state $left = $count;
while ($left) {
my $item = $base->();
return unless ref $item;
$left--;
}
return $base->();
};
};
}
sub skip_while {
my ($self, $predicate) = @_;
return _create sub {
return sub {
state $base = $self->new();
state $skip = 1;
while ($skip) {
my $item = $base->();
return unless ref $item;
local $_ = $$item;
$skip &= !! $predicate->($_);
return $item unless $skip;
}
return $base->();
};
}
}
sub element_at {
my ($self, $index) = @_;
Carp::cluck "Index out of range for element_at" if $index < 0;
my $base = $self->new();
while (1) {
my $item = $base->();
do {
use Data::Dumper;
warn Dumper[$self->count(sub { warn Data::Dumper::Dumper($_); 1; })];
Carp::cluck "Index out of range for element_at";
} unless ref $item;
return $$item unless $index--;
}
Carp::confess("Impossible");
}
sub last {
( run in 1.392 second using v1.01-cache-2.11-cpan-140bd7fdf52 )