Control Flow

7.1 Conditionals

my $score = 85;
if $score >= 90 {                 # no parentheses needed
    say 'A';
}
elsif $score >= 80 {
    say 'B';
}
else {
    say 'C';
}
unless $score < 50 { say 'Passed' }
say 'Excellent' if $score > 80;   # statement modifiers
my $grade = $score >= 50 ?? 'pass' !! 'fail';

# with / without / orwith: test definedness and topicalize
my $maybe = %*ENV<HOME>;
with $maybe { say "Home is $_" } else { say 'No HOME' }
without $maybe { say 'undefined' }
say "Found: $_" with 'some value';

7.2 given/when (Topicalizer and Smartmatch)

when smartmatches the topic ($_ ~~ X) and automatically breaks out of the enclosing block. Use proceed to continue to the next when, and succeed to leave early.

sub classify($x) {
    given $x {
        when Int where * < 0 { 'negative integer' }
        when 0               { 'zero' }
        when Int             { 'positive integer' }
        when Str             { "string '$_'" }
        when /^\d+$/         { 'numeric string' }    # never reached for Str above, shown for syntax
        when 1..10 | 100     { 'in range' }
        default              { 'something else' }
    }
}
say classify($_) for -5, 0, 7, 'hi', 3.5;

7.3 Loops

for 1..5 { .say }                           # $_ is the topic
for 1..5 -> $i { say $i * 2 }               # pointy block names the variable
for <a b c>.kv -> $index, $value { say "$index: $value" }   # two at a time
for %(a => 1, b => 2).kv -> $k, $v { say "$k=$v" }
for 1..10 -> $a, $b { say "$a $b" }         # iterate in pairs
for (1, 2, 3) Z (<x y z>) -> ($n, $l) { say "$n$l" }        # destructuring

my $i = 0;
while $i < 3 { say $i++ }
until $i == 0 { $i-- }
repeat { say 'at least once' } while False;
repeat { $i++ } until $i >= 3;
loop (my $j = 0; $j < 3; $j++) { say $j }   # C-style
loop { last if ++$i > 10 }                  # infinite loop with last

OUTER: for 1..3 -> $x {
    for 1..3 -> $y {
        next OUTER if $y == 2;
        last OUTER if $x == 3;
        say "$x,$y";
    }
}
# next, last, redo; loops return values too:
my @squares = do for 1..5 { $_ ** 2 };      # (1 4 9 16 25)