Sequences, Laziness and gather/take

12.1 The Sequence Operator

say (1, 2 ... 10);                     # arithmetic: (1 2 3 4 5 6 7 8 9 10)
say (1, 3 ... 15);                     # step 2
say (2, 4, 8 ... 1024);                # geometric (deduced)
say (1, 1, * + * ... *)[^10];          # Fibonacci, lazy and infinite
say (1, { $_ * 3 } ... * > 1000);      # generator block with an end condition
say ('a' ... 'e');
say (10, 8 ... 0);
say (1 ...^ 5);                        # excludes the end point: (1 2 3 4)
my @primes = (2..*).grep(*.is-prime);  # lazy infinite list
say @primes[^10];                      # (2 3 5 7 11 13 17 19 23 29)
say @primes[99];                       # the 100th prime: 541
my @fib = 0, 1, * + * ... *;
say @fib[50];                          # 12586269025
say (1, 2, 4 ... *).first(* > 1_000_000);

12.2 Lazy Lists

my $lazy = (1..*).map(* ** 2);
say $lazy.is-lazy;                     # True
say $lazy[^5];                         # (1 4 9 16 25): only computes what's needed
say (1..*).grep(* %% 7).head(3);       # (7 14 21)
my @eager = eager (1..5).map(* * 2);   # force evaluation
say lazy (1..3).map({ say "computing $_"; $_ });   # nothing computed until used

12.3 gather/take: Generators

my @evens = gather for 1..10 { take $_ if $_ %% 2 };
say @evens;                            # [2 4 6 8 10]

sub collatz(Int $n is copy) {
    gather {
        take $n;
        while $n != 1 {
            $n = $n %% 2 ?? $n div 2 !! 3 * $n + 1;
            take $n;
        }
    }
}
say collatz(6);                        # (6 3 10 5 16 8 4 2 1)

my $infinite = gather { my $i = 0; loop { take $i++ } };   # lazy
say $infinite[^5];
# take can be called from nested subs (dynamically scoped to the gather)
sub helper($x) { take $x * 10 }
say gather { helper($_) for 1..3 };    # (10 20 30)