syntax gather take

Documentation for syntax gather take assembled from the following types:

language documentation Control flow

From Control flow

(Control flow) control flow gather take 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 block. 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 a strictly increasing order):

sub factorsInt: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␤»

gather/take can generate values lazily, depending on context. If you want to force lazy evaluation use the lazy subroutine or method. Binding to a scalar or sigilless container will also force laziness. 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 gather/take also work for hashes. The return value is still a Seq but the assignment to a hash in the following example makes it a hash.

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