In the future — the not too distant future, if I read the ROADMAP correctly — Rakudo will be able to handle potentially infinite streams of values.
my @a = gather {
my $count = 5;
take $count++ while True;
};
.say for @a[0..4]; # 5\n6\n7\n8\n9
Actually, not only the gather
construct does this, but lists themselves:
my @a = 5 ... *;
.say for @a[0..4]; # 5\n6\n7\n8\n9
Neither of these two work yet. The former hangs, and the latter just earned me a rakudobug. (Update 2009-10-13: A rakudobug which, 46 hours later, moritz++ fixes. Complaining is extra rewarding when the reaction is swift.)
Anyway, awaiting all that lazy goodness, we can always fall back on the "old-fashioned" way of lazily generating a stream, namely a closure. The following code does work in Rakudo:
class LazyIterator {
has $!it;
method get() {
$!it();
}
}
class Counter is LazyIterator {
method new(Int $start) {
my $count = $start;
self.bless(*, :it({ $count++ }));
}
}
my $c = Counter.new(5);
say $c.get for 0..4; # 5\n6\n7\n8\n9
In our daily fight against scattered and tangled code, closures are a fine weapon to have in one's arsenal. The fact that they are capable of giving us laziness in Rakudo today, before it is actually implemented, is a nice example of that.