Beginner

Control Flow in Raku

Learn conditionals, loops, and branching in Raku — including if/elsif/else, given/when smart matching, ranges, and loop control with practical Docker-ready examples

Control flow determines the order in which your code executes — which branches run, how many times a block repeats, and when to stop. Raku gives you an unusually rich toolkit here, staying true to its TIMTOWTDI (“There Is More Than One Way To Do It”) philosophy.

As a multi-paradigm language, Raku offers familiar structured constructs (if, while, for) alongside expressive features that other languages lack: postfix statement modifiers, the given/when topicalizer built on smart matching, and unless/until as readable negations. Conditions also rely on Raku’s notion of truthiness — 0, empty strings, empty collections, and type objects like Nil are all falsy.

In this tutorial you’ll learn how to branch with if/elsif/else and unless, how to write switch-style logic with given/when, how to iterate using for, while, until, and the bare loop, and how to steer iteration with last, next, and loop labels.

Conditionals: if, elsif, else, unless

Raku’s if needs no parentheses around the condition. It pairs with elsif and else, and adds unless for the negated case. Raku also has a ternary operator written ?? !!, and postfix conditionals that let you attach a condition to the end of a single statement.

Create a file named conditionals.raku:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# if / elsif / else — no parentheses required
my $temp = 72;

if $temp > 85 {
    say "It's hot";
} elsif $temp < 50 {
    say "It's cold";
} else {
    say "It's pleasant";
}

# unless — the readable opposite of if
my $logged-in = False;
unless $logged-in {
    say "Please log in";
}

# Postfix conditionals (statement modifiers)
say "Even number" if 10 %% 2;   # %% means "is divisible by"
say "Not zero"   unless 0;       # 0 is falsy in Raku

# Ternary: condition ?? value-if-true !! value-if-false
my $age = 20;
my $status = $age >= 18 ?? "adult" !! "minor";
say $status;

The postfix form (say "..." if condition) reads almost like English and is idiomatic Raku for short, guarded statements.

Switch with given/when

Raku’s switch statement is given/when. The given block sets the topic variable $_, and each when performs a smart match (~~) against it. Smart matching is what makes when so powerful: it works with ranges, types, regexes, and more — not just equality.

Create a file named given_when.raku:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Numeric ranges as match conditions
my $grade = 85;

given $grade {
    when 90..100 { say "A" }
    when 80..89  { say "B" }
    when 70..79  { say "C" }
    default      { say "F" }
}

# Smart matching against types
my $value = "hello";

given $value {
    when Int { say "It's an integer" }
    when Str { say "It's a string" }
    when Rat { say "It's a rational" }
    default  { say "Unknown type" }
}

# Smart matching against a regex
given "2026-06-09" {
    when /^ \d**4 '-' \d**2 '-' \d**2 $/ { say "Looks like a date" }
    default                              { say "Not a date" }
}

Each when block automatically succeeds (breaks out) after matching, so there’s no C-style fall-through and no break keyword to remember.

Loops: for, while, until, and loop

Raku’s for iterates over any list or range. You can name the loop variable with the pointy-block arrow ->, or use the implicit topic $_. while and until are condition-driven, and the bare loop runs forever until you break out.

Create a file named loops.raku:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# for over a range, with a named loop variable
for 1..5 -> $n {
    print $n;
}
say "";  # print a trailing newline

# for over a list, using the implicit topic $_
for <apple banana cherry> {
    say "Fruit: $_";
}

# Iterate with index using .kv (key => value pairs)
for <a b c>.kv -> $index, $letter {
    say "$index => $letter";
}

# while loop
my $count = 3;
while $count > 0 {
    say "Countdown: $count";
    $count--;
}

# until loop — runs while the condition is false
my $i = 0;
until $i >= 3 {
    say "Up: $i";
    $i++;
}

# Bare loop — an infinite loop with an explicit exit
my $sum = 0;
loop {
    $sum += 10;
    last if $sum >= 30;
}
say "Sum reached $sum";

Note <apple banana cherry> is the angle-bracket word-list quoting — a quick way to build a list of strings without commas or quotes.

Loop Control: last, next, and labels

Inside any loop you can use last to exit (like break), next to skip to the next iteration (like continue), and redo to repeat the current iteration. For nested loops, labels let you control an outer loop from inside an inner one.

Create a file named loop_control.raku:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# last — exit the loop early
for 1..10 -> $n {
    last if $n > 3;
    say "Counting: $n";
}

# next — skip to the next iteration
for 1..6 -> $n {
    next if $n %% 2;   # skip even numbers
    say "Odd: $n";
}

# Labels let inner loops control outer loops
OUTER: for 1..3 -> $row {
    for 1..3 -> $col {
        next OUTER if $col == 2;
        say "row $row, col $col";
    }
}

The label OUTER: names the outer for loop, so next OUTER jumps to the outer loop’s next iteration rather than the inner one’s.

Running with Docker

1
2
3
4
5
6
7
8
# Pull the official Rakudo Star image
docker pull rakudo-star:alpine

# Run each example
docker run --rm -v $(pwd):/app -w /app rakudo-star:alpine raku conditionals.raku
docker run --rm -v $(pwd):/app -w /app rakudo-star:alpine raku given_when.raku
docker run --rm -v $(pwd):/app -w /app rakudo-star:alpine raku loops.raku
docker run --rm -v $(pwd):/app -w /app rakudo-star:alpine raku loop_control.raku

Expected Output

Running conditionals.raku:

It's pleasant
Please log in
Even number
Not zero
adult

Running given_when.raku:

B
It's a string
Looks like a date

Running loops.raku:

12345
Fruit: apple
Fruit: banana
Fruit: cherry
0 => a
1 => b
2 => c
Countdown: 3
Countdown: 2
Countdown: 1
Up: 0
Up: 1
Up: 2
Sum reached 30

Running loop_control.raku:

Counting: 1
Counting: 2
Counting: 3
Odd: 1
Odd: 3
Odd: 5
row 1, col 1
row 2, col 1
row 3, col 1

Key Concepts

  • No parentheses neededif, while, and for take their conditions directly; braces define the block.
  • Postfix modifierssay "hi" if $cond and say "hi" unless $cond make short, guarded statements read like English.
  • unless and until — readable negations of if and while, avoiding clumsy if !condition logic.
  • Truthiness0, "", empty collections, and type objects like Nil are falsy; most other values are true.
  • given/when uses smart matchingwhen matches against ranges, types, and regexes, not just equality, and breaks automatically with no fall-through.
  • The topic variable $_ — set implicitly by given and bare for blocks, enabling concise code.
  • Ranges drive iteration1..5 and word lists like <a b c> are first-class iterables for for loops.
  • Loop control with labelslast, next, and redo steer iteration, and named labels let inner loops control outer ones.

Running Today

All examples can be run using Docker:

docker pull rakudo-star:alpine
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining