Statement prefixes

Prefixes that alter the behavior of a statement or a set of them

Statement prefixes are written in front of a statement, and change their meaning, their output, or the moment they are going to be run. Since they have a specific behavior, they are also sometimes specific to some statement or group of statements.

lazy|Syntax,lazy (statement prefix)

As a statement prefix, lazy acts in front of any statement, including for loops, saving the execution for when the variable they are assigned to is actually needed.

my $incremented = 0;
my $var = lazy for <1 2 3 4> -> $d {
    $incremented++
};
say $incremented; # OUTPUT: «0␤»
say eager $var;   # OUTPUT: «(0 1 2 3)␤»
say $incremented; # OUTPUT: «4␤»

The $incremented variable is only incremented, that is, the internal part of the loop is only run when we eagerly evaluate the variable $var that contains the lazy loop. Eagerness can be applied on a variable in other ways, such as calling the .eager method on it.

my @array = lazy { (^3).map( *² )  };
say @array;       # OUTPUT: «[...]␤»
say @array.eager; # OUTPUT: «[0 1 4]␤»

This prefix can also be used in front of gather to make the inner statements behave lazily; in general, any set of statements that returns a value will be made lazy using this.

eager|Syntax,eager (statement prefix)

The eager statement prefix will eagerly return the result of the statements behind, throwing away laziness and returning the result.

my $result := eager gather { for 1..3 { say "Hey"; take $_² } };
say $result[0]; # OUTPUT: «Hey␤Hey␤Hey␤1␤»

gather is implicitly lazy when bound to a scalar. However, with eager as a statement prefix it will run all three iterations in the loop, as shown by the printed "Hey", even if we are just requesting the first one in a row.

hyper|Syntax,hyper (statement prefix), race|Syntax,race (statement prefix)

A for loop will automatically serialize any HyperSeq or RaceSeq used in it; on the other hand hyper and race use (maybe simultaneous) threads to run different iterations in a loop:

my @a = hyper for ^100_000 { .is-prime }

This code is around 3x faster than the bare for. But there are a couple of caveats here:

  • The operation inside the loop should take enough time for threading to make sense.

  • There should be no read or write access to the same data structure inside the loop. Let the loop produce a result, and assign it.

  • If there's an I/O operation inside the loop, there might be some contention so please avoid it.

Main difference between hyper and race is the ordering of results. Use hyper if you need the loop results to be produced in order, race if you don't care.

quietly|Syntax,quietly (statement prefix)

As a prefix, quietly suppresses all runtime warnings produced by the block or statement it precedes.

sub marine() {};
quietly say ~&marine; # OUTPUT: «marine␤»
sub told-you { warn 'hey...' };
quietly { told-you; warn 'kaput!' };
warn 'Telling you now!';  # OUTPUT: «Telling you now!␤ [...] ␤»

Calling .Str on code produces a warning. Preceding the code with quietly will just produce the output without warning.

try|Syntax,try (statement prefix)

If you use try in front of a statement, it will contain the exception produced in it and store it in the $! variable, just like when it's used in front of a block.

try [].pop;
say $!; # OUTPUT: «Cannot pop from an empty Array␤..»

do|Syntax,do (statement prefix)

do can be used as a statement prefix to disambiguate the statement they precede; this is needed, for instance, if you want to assign the result of a for statement. A bare for will fail, but this will work:

my $counter = 0;
my $result = do for ^5 { $counter++ };
say $counter; # OUTPUT: «5␤»
say $result;  # OUTPUT: «(0 1 2 3 4)␤»

do is equivalent, as in other cases, to surrounding a statement with a parenthesis. It can be used as an alternative with a (possibly more) straightforward syntax.

sink|Syntax,sink (statement prefix)

As in the case of the routine, sink will run the statement, throwing away the result. Use it in case you want to run some statement for the side effects it produces.

my $counter = 0;
my $result = sink for ^5 { $counter++ };
say $counter; #  OUTPUT: «5␤»
say $result;  #  OUTPUT: «(Any)␤»

The sink statement prefix will also convert Failures into exceptions:

sub find-the-number ( Int $n where $n < 10 ) {
    if $n == 7 {
        return True;
    } else {
        fail "Not that number" ;
    }
}
for 1..^10 {
    try {
        sink find-the-number($_);
    };
    say "Found $_" unless $!;
}

In this case, we will know that the number has been found only when the try block is not catching an exception.

react|Syntax,react (statement prefix)

react can be used in concurrent programs to create blocks of code that run whenever some event occurs. It works with blocks, and also as a statement prefix.

my Channel $KXGA .= new;
for ^100 {
    $KXGA.send( (100000..200000).pick );
}

my @sums = ( start react whenever $KXGA -> $number {
    say "In thread ", $*THREAD.id;
    say "→ ", (^$number).sum;
} ) for ^10;

start { sleep 10; $KXGA.close(); }

await @sums;

In this case react prefixes whenever, which makes a long sum with every number read from a channel.

See Also

Containers

A low-level explanation of Raku containers

Contexts and contextualizers

What are contexts and how to switch into them

Control flow

Statements used to control the flow of execution

Enumeration

An example using the enum type

Exceptions

Using exceptions in Raku

Functions

Functions and functional programming in Raku

Grammars

Parsing and interpreting text

Hashes and maps

Working with associative arrays/dictionaries/hashes

Input/Output the definitive guide

Correctly use Raku IO

Lists, sequences, and arrays

Positional data constructs

Metaobject protocol (MOP)

Introspection and the Raku object system

Native calling interface

Call into dynamic libraries that follow the C calling convention

Raku native types

Using the types the compiler and hardware make available to you

Newline handling in Raku

How the different newline characters are handled, and how to change the behavior

Numerics

Numeric types available in Raku

Object orientation

Object orientation in Raku

Operators

Common Raku infixes, prefixes, postfixes, and more!

Packages

Organizing and referencing namespaced program elements

Performance

Measuring and improving runtime or compile-time performance

Phasers

Program execution phases and corresponding phaser blocks

Pragmas

Special modules that define certain aspects of the behavior of the code

Quoting constructs

Writing strings and word lists, in Raku

Regexes

Pattern matching against strings

Sets, bags, and mixes

Unordered collections of unique and weighted objects in Raku

Signature literals

A guide to signatures in Raku

Data structures

How Raku deals with data structures and what we can expect from them

Subscripts

Accessing data structure elements by index or key

Syntax

General rules of Raku syntax

System interaction

Working with the underlying operating system and running applications

Date and time functions

Processing date and time in Raku

Traits

Compile-time specification of behavior made easy

Unicode versus ASCII symbols

Unicode symbols and their ASCII equivalents

Unicode

Unicode support in Raku

Variables

Variables in Raku

Independent routines

Routines not defined within any class or role.

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.