Raku Programming/Control Structures

Flow Control
We've seen in earlier chapters how to create variables and use them to perform basic arithmetic and other operations. Now we're going to introduce the idea of flow control, using special constructs for branching and looping.

Blocks
Blocks are chunks of code inside  curly brackets. These are set apart from the rest of the nearby code in a variety of ways. They also define a new scope for variables: Variables defined with  and used inside a block are not visible or usable outside the block. This enables code to be compartmentalized, to ensure that variables only intended for temporary use are only used temporarily.

Branching
Branching can occur using one of two statements: an if and an unless. may optionally have an else clause as well. An  statement evaluates a given condition and if it's a true statement, the block following the   is executed. When the statement is false, the  block, if any, is executed instead. The  statement does the opposite. It evaluates a condition and only executes its block when the condition is false. You cannot use an   clause when using.

Relational Operators
There are a variety of relational operators that can be used to determine a truth value. Here are some:

All of these operators return a boolean value, and can be assigned to a variable:

The parentheses above are used only for clarity; they are not actually necessary.

/
Let's start off with an example:

Notice in this example above that there is a space between the  and the. This is important and is not optional. The parsing rules for Raku are clear on this point: Any word followed by a  opening parenthesis is treated as a subroutine call. The space differentiates this statement from a subroutine call and lets the parser know that this is a conditional:

To avoid all confusion, the parenthesis can be safely omitted:

has the opposite behavior of :

No  clause is allowed after.

Postfix Syntax
and  aren't just useful for marking blocks to be conditionally executed. They can also be applied in a natural way to the end of a statement to only affect that one statement:

These two lines of code above only execute if their conditions are satisfied properly. The first sets  to 5 if   is equal to 3. The second increments  unless the sum of   is greater than 8.

Smart Matching
Sometimes you want to check if two things match. The relational operator  checks if two values are equal, but that's very limited. What if we wanted to check other equality relationships? What we want is an operator that just does what we mean, no matter what that might be. This magical operator is the smart match operator  operator, you probably immediately think about strings. The smart match operator does a lot with strings, but isn't restricted to them.

Here are some examples of the smart match operator in action:

As you can see, the smart match operator can be used in a variety of ways to test two things to see if they match in some way. Above we saw an example of a regular expression, which we will discuss in more detail in later chapters. This also isn't a comprehensive list of things that can be matched, we will see more things throughout the book.

Given / When
Raku has a facility for matching a quantity against a number of different alternatives. This structure is the  and   blocks.

Each  is a smart match. The code above is equivalent to this:

The /  structure is more concise than the  /, and internally it might be implemented in a more optimized way.

Loops
Loops are ways to repeat certain groups of statements more than once. Raku has a number of available types of loops that can be used, each of which has different purposes.

loops
for blocks take an array or range argument, and iterate over every element. In the most basic case,  assigns each successive value to the default variable. Alternatively, a specific variable can be listed to receive the value. Here are several examples of  blocks:

In all the examples above, the array argument to  can optionally be enclosed in parenthesis too. The special "pointy" syntax  will be explained in more detail later, although it's worth noting here that we can extend it to read multiple values from the array at each loop iteration:

This prints the following lines:

Even: 0 Odd: 1 Even: 2 Odd: 3 Even: 4 Odd: 5

can also be used as a statement postfix, like we saw with  and , although with some caveats:

C programmers will recognize the behavior of the  construct, which is the same format and behavior as the   loop in C. Raku has reused the name   for the array looping construct that we saw in the previous section, and uses the name   to describe the incremental behavior of C's loops. Here is the  structure:

In general,  takes these three components:

loop ( INITIALIZER ; CONDITION ; INCREMENTER )

The  in a   is a line of code that executes before the loop begins, but has the same lexical scope as the loop body. The  is a boolean test that's checked before every iteration. If the test is false, the loop exits, if it is true, the loop repeats. The  is a statement that happens at the end of the loop, before the next iteration begins. All of these parts may be optionally omitted. Here are five ways to write the same loop:

If you want an infinite loop, you can also omit the parentheses instead of using :

blocks
A repeat block will execute its body at least once as the condition follows after the block. In the example below you can see that even though  is larger than two, the block will still run.