One of the main problems is that you store it in an array, which, of course, stores all its values.
The next problem is a little more subtle, the syntax of LIST , CODE ... END
the point sequence generator does not know how many of the previous values ββthe CODE
part will request, so it stores all of them.
(He could look at arity / count CODE
, but at the moment this is not like experimenting on REPL)
Then the problem arises of using &postcircumfix:<[ ]>
on Seq calls .cache
on the assumption that at some point you will ask for a different value.
(From looking at the source for Seq.AT-POS)
It is possible that future implementation may be better for each of these shortcomings.
You can create a sequence using another function to circumvent the current syntax limitations of a point sequence generator.
sub fibonacci-seq (){ gather { take my $a = 0; take my $b = 1; loop { take my $c = $a + $b; $a = $b; $b = $c; } }.lazy }
If you just repeat the values, you can just use them as is.
my $v; for fibonacci-seq() { if $_ > 1000 { $v = $_; last; } } say $v; my $count = 100000; for fibonacci-seq() { if $count-- <= 0 { $v = $_; last; } } say chars $v; # 20899
You can also use Iterator directly. Although this is not necessary in most cases.
sub fibonacci ( UInt $n ) { # have to get a new iterator each time this is called my \iterator = fibonacci-seq().iterator; for ^$n { return Nil if iterator.pull-one =:= IterationEnd; } my \result = iterator.pull-one; result =:= IterationEnd ?? Nil !! result }
If you have a fairly recent version of Rakudo, you can use skip-at-least-pull-one
.
sub fibonacci ( UInt $n ) { # have to get a new iterator each time this is called my \result = fibonacci-seq().iterator.skip-at-least-pull-one($n); result =:= IterationEnd ?? Nil !! result }
You can also implement the Iterator class by wrapping it in Seq .
(this is basically how the methods that return the sequences are written to the Rakudo core)
sub fibonacci-seq2 () { Seq.new: class :: does Iterator { has Int $!a = 0; has Int $!b = 1; method pull-one { my $current = $!a; my $c = $!a + $!b; $!a = $!b; $!b = $c; $current; } # indicate that this should never be eagerly iterated # which is recommended on infinite generators method is-lazy ( --> True ) {} }.new }