The Raku Programming Language Collect, Conserve and Remaster Project
Originally published on 11 October 2009 by Carl Mäsak.
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.