# 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 `my` 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. `if` may optionally have an else clause as well. An `if` statement evaluates a given condition and if it's a true statement, the block following the `if` is executed. When the statement is false, the `else` block, if any, is executed instead. The `unless` statement does the opposite. It evaluates a condition and only executes its block when the condition is false. You cannot use an `else` clause when using `unless`.

### Relational Operators

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

```\$x == \$y;                  # \$x and \$y are equal
\$x > \$y;                   # \$x is greater than \$y
\$x >= \$y;                  # \$x is greater than or equal to \$y
\$x < \$y;                   # \$x is less than \$y
\$x <= \$y;                  # \$x is less than or equal to \$y
\$x != \$y;                  # \$x is not equal to \$y
```

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

```\$x = (5 > 3);              # \$x is True
\$y = (5 == 3);             # \$y is False
```

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

### `if`/`unless`

Let's start off with an example:

```my Int \$x = 5;
if (\$x > 3) {
say '\$x is greater than 3';         # This prints
}
else {
say '\$x is not greater than 3';     # This doesn't
}
```

Notice in this example above that there is a space between the `if` and the `(\$x > 3)`. 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:

```if(\$x > 5) {   # Calls subroutine "if"
}

if (\$x > 5) {  # An if conditional
}
```

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

```if \$x > 5 {     # Always a condition
}
```

### `unless`

`unless` has the opposite behavior of `if`:

```my Int \$x = 5;
unless \$x > 3 {
say '\$x is not greater than 3';         # This doesn't print
}
```

No `else` clause is allowed after `unless`.

### Postfix Syntax

`if` and `unless` 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:

```\$x = 5 if \$y == 3;
\$z++ unless \$x + \$y > 8;
```

These two lines of code above only execute if their conditions are satisfied properly. The first sets `\$x` to 5 if `\$y` is equal to 3. The second increments `\$z` unless the sum of `\$x + \$y` 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 `~~`.

Now, when you see the `~~` 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:

```5 ~~ "5";                          # true, same numerical value
["a", "b"] ~~ *, "a", *;           # true, "a" contained in the array
("a" => 1, "b" => 2) ~~ *, "b", *; # true, hash contains a "b" key
"c" ~~ /c/;                        # true, "c" matches the regex /c/
3 ~~ Int                           # true, 3 is an Int
```

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 `given` and `when` blocks.

```given \$x {
when Bool { say '\$x is the boolean quantity ' ~ \$x; }
when Int { when 5 { say '\$x is the number 5'; } }
when "abc" { say '\$x is the string "abc"'; }
}
```

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

```if \$x ~~ 5 {
say '\$x is the number 5';
}
elsif \$x ~~ "abc" {
say '\$x is the string "abc"';
}
elsif \$x ~~ Bool {
say '\$x is the boolean quantity ' ~\$x;
}
```

The `given`/`when` structure is more concise than the `if`/`else`, 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.

### `for` loops

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

```# Prints the numbers "12345"
for 1..5 {          # Assign each value to \$_
.print;           # print \$_;
}

# Same thing, but using an array
my @nums = 1..5;
for @nums {
.print;
}

# Same, but uses an array that's not a range
my @nums = (1, 2, 3, 4, 5);
for @nums {
.print;
}

# Using a different variable than \$_
for 1..5 -> \$var {
print \$var;
}
```

In all the examples above, the array argument to `for` 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:

```my @nums = 0..5;
for @nums -> \$even, \$odd {
say "Even: \$even Odd: \$odd";
}
```

This prints the following lines:

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

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

```print \$_ for (1..5);    # Prints "12345"
print for (1..5);        # Parse Error! Print requires an argument
.print for 1..5;  # Prints "12345"
```

### `loop`

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

```loop (my \$i = 0; \$i <= 5; \$i++) {
print \$i;            # "12345"
}
```

In general, `loop` takes these three components:

```loop ( INITIALIZER ; CONDITION ; INCREMENTER )
```

The `INITIALIZER` in a `loop` is a line of code that executes before the loop begins, but has the same lexical scope as the loop body. The `CONDITION` 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 `INCREMENTER` 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:

```loop (my \$i = 0; \$i <= 5; \$i++) {
print \$i;            # "12345"
}

my \$i = 0;    # Small Difference: \$i is scoped differently
loop ( ; \$i <= 5; \$i++) {
print \$i;
}

loop (my \$i = 0; \$i <= 5; ) {
print \$i;            # "12345"
\$i++;
}

loop (my \$i = 0; ; \$i++) {
last unless (\$i <= 5);
print \$i;            # "12345"
}

my \$i = 0;
loop ( ; ; ) {
last unless (\$i <= 5);
print \$i;            # "12345"
\$i++;
}
```

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

```my \$i = 0;
loop {   # Possibly infinite loop
last unless (\$i <= 5);
print \$i;            # "12345"
\$i++;
}
```

### `repeat` 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 `\$i` is larger than two, the block will still run.

```my \$i = 3;
repeat {
say \$i;
} while \$i < 2;
```