In Control flow§

See primary documentation in context for gather/take.

gather is a statement or block prefix that returns a sequence of values. The values come from calls to take in the dynamic scope of the gather code. In the following example, we implement a subroutine to compute the factors of an integer with gather (note that the factors are not generated in order):

sub factors( Int:D \n ) {
    my $k = 1;
    gather {
        while $k**2 < n {
            if n %% $k {
                take $k;
                take n div $k;
            }
            $k++;
        }
        take $k if $k**2 == n;
    }
}

say factors(36); # OUTPUT: «1, 36, 2, 18, 3, 12, 4, 9, 6␤»

The gather/take combination can generate values lazily, depending on context. Binding to a scalar or sigilless container will force laziness. If you want to force lazy evaluation use the lazy subroutine or method. For example:

my @vals = lazy gather {
    take 1;
    say "Produced a value";
    take 2;
}
say @vals[0];
say 'between consumption of two values';
say @vals[1];

# OUTPUT:
# 1
# between consumption of two values
# Produced a value
# 2

gather/take is scoped dynamically, so you can call take from subs or methods that are called from within gather:

sub weird(@elems, :$direction = 'forward') {
    my %direction = (
        forward  => sub { take $_ for @elems },
        backward => sub { take $_ for @elems.reverse },
        random   => sub { take $_ for @elems.pick(*) },
    );
    return gather %direction{$direction}();
}

say weird(<a b c>, :direction<backward> );          # OUTPUT: «(c b a)␤»

If values need to be mutable on the caller side, use take-rw.

Note that the Seq created by gather/take may be coerced to another type. An example with assignment to a hash:

my %h = gather { take "foo" => 1; take "bar" => 2};
say %h;                   # OUTPUT: «{bar => 2, foo => 1}␤»

Note: gather/take must not be used to collect results from react/whenever. The whenever block is not run from the thread that runs the gather/react, but the thread that runs the emit. On this thread, there is no handler for the control exception thrown by take, causing it to error out.