Skip to content

Instantly share code, notes, and snippets.

@hoehrmann
Last active December 15, 2015 01:39
Show Gist options
  • Save hoehrmann/5181285 to your computer and use it in GitHub Desktop.
Save hoehrmann/5181285 to your computer and use it in GitHub Desktop.
Lazy lists with state variables and $StopIteration
package Acme::IEnumerable;
use v5.16;
use strict;
use warnings;
our $StopIteration = {};
sub integers {
my ($class) = @_;
return bless sub {
state $counter = 0;
return $counter++;
}, $class;
}
sub all {
my ($self, $predicate) = @_;
eval {
while (1) {
local $_ = $self->();
return unless $predicate->($_);
}
};
die $@ if $@ ne '' and $@ != $StopIteration;
return $@ == $StopIteration;
}
sub take {
my ($self, $count) = @_;
return bless sub {
state $left = $count;
if ($left > 0) {
$left -= 1;
return $self->();
}
die $StopIteration;
}, ref $self;
}
sub where {
my ($self, $predicate) = @_;
return bless sub {
state $index = 0;
while (1) {
local $_ = $self->();
return $_ if $predicate->($_, $index++);
}
}, ref $self;
}
sub to_list {
my ($self) = @_;
my @result;
eval {
push @result, $self->() while 1;
};
die $@ unless $@ == $StopIteration;
return @result;
}
package main;
use v5.16;
my $range = Acme::IEnumerable->integers()->take(10);
say $range->where(sub { $_ > 5 })->to_list;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment