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 )