Control Flow
Conditionals, loops, and exception handling.
Conditionals
If / Elsif / Else
my int $x = 10;
if ($x > 10) {
say("Greater than 10");
} elsif ($x == 10) {
say("Equal to 10");
} else {
say("Less than 10");
}
Unless
unless is the opposite of if — it executes when the condition is false:
my int $logged_in = 0;
unless ($logged_in) {
say("Please log in");
}
# With else (no elsif allowed with unless)
unless ($logged_in) {
say("Please log in");
} else {
say("Welcome back");
}
# Equivalent to:
if (!$logged_in) {
say("Please log in");
}
Ternary Operator
my int $age = 20;
my str $status = $age >= 18 ? "adult" : "minor";
say($status); # "adult"
Loops
While Loop
my int $i = 0;
while ($i < 5) {
say($i);
$i++;
}
Until Loop
until is the opposite of while — it loops while the condition is false:
my int $count = 0;
until ($count >= 5) {
say($count);
$count++;
}
# Equivalent to: while ($count < 5) { ... }
Do-While Loop
my int $i = 0;
do {
say($i);
$i++;
} while ($i < 5);
For Loop
for (my int $i = 0; $i < 5; $i++) {
say("i = " . $i);
}
Foreach Loop
Iterate over arrays:
my array @fruits = ["apple", "banana", "cherry"];
# With type declaration
foreach my str $fruit (@fruits) {
say($fruit);
}
# Without type (uses existing variable)
my str $item;
foreach $item (@fruits) {
say($item);
}
# "for" works like "foreach" with arrays
for my str $fruit (@fruits) {
say($fruit);
}
Increment/Decrement
my int $x = 5;
$x++; # Post-increment: returns 5, then x becomes 6
++$x; # Pre-increment: x becomes 7, returns 7
$x--; # Post-decrement: returns 7, then x becomes 6
--$x; # Pre-decrement: x becomes 5, returns 5
# Often used in loops
my int $i = 0;
while ($i < 10) {
say($i++); # Print then increment
}
Loop Control
for (my int $i = 0; $i < 10; $i++) {
if ($i == 3) {
next; # Skip to next iteration
}
if ($i == 7) {
last; # Exit loop
}
say($i);
}
# Output: 0, 1, 2, 4, 5, 6
# redo - restart current iteration without re-checking condition
my int $attempts = 0;
while ($attempts < 3) {
$attempts++;
my str $input = readline();
if ($input eq "") {
say("Input required");
redo; # Restart iteration (don't re-check or advance)
}
}
Labeled Loops
Labels allow breaking out of nested loops:
OUTER: for (my int $i = 0; $i < 5; $i++) {
INNER: for (my int $j = 0; $j < 5; $j++) {
if ($j == 2) {
next INNER; # Skip to next inner iteration
}
if ($i == 3) {
last OUTER; # Exit both loops
}
say("i=" . $i . " j=" . $j);
}
}
Functional Array Operations
Strada supports Perl-style map, grep, and sort for powerful array transformations. Use $_ for the current element.
Map (Transform)
my array @nums = (1, 2, 3, 4, 5);
# Transform each element
my array @doubled = map { $_ * 2 } @nums;
# Result: (2, 4, 6, 8, 10)
Map to Hash (Perl Idiom)
Create lookup hashes using the fat arrow (=>):
my array @fruits = ("apple", "banana", "cherry");
# The classic Perl idiom - works in Strada!
my hash %lookup = map { $_ => 1 } @fruits;
# Fast O(1) membership testing
if (exists($lookup{"apple"})) {
say("Found apple!");
}
Grep (Filter)
my array @nums = (1, 2, 3, 4, 5, 6);
# Keep only even numbers
my array @evens = grep { $_ % 2 == 0 } @nums;
# Result: (2, 4, 6)
Sort
my array @nums = (5, 2, 8, 1, 9);
# Numeric sort (ascending) - use $a, $b with spaceship
my array @asc = sort { $a <=> $b } @nums;
# Descending
my array @desc = sort { $b <=> $a } @nums;
Chaining Operations
# Filter, transform, and sort in one line
my array @result = sort { $a <=> $b } map { $_ * 10 } grep { $_ > 3 } @data;
See Also: Built-in Functions Reference for more examples.
Exception Handling
Try / Catch / Throw
func divide(int $a, int $b) int {
if ($b == 0) {
throw "Division by zero!";
}
return $a / $b;
}
func main() int {
try {
my int $result = divide(10, 0);
say("Result: " . $result);
} catch ($e) {
say("Error: " . $e);
}
say("Program continues...");
return 0;
}
Exception Values
The
throw statement can throw any value (string, number, etc.).
The catch block receives that value in its parameter.
Nested Try/Catch
try {
try {
throw "Inner error";
} catch ($e) {
say("Caught inner: " . $e);
throw "Re-throwing"; # Re-throw or throw new
}
} catch ($e) {
say("Caught outer: " . $e);
}
Goto and Labels
For exceptional control flow (use sparingly):
func main() int {
my int $i = 0;
start:
say($i);
$i++;
if ($i < 5) {
goto start;
}
say("Done");
return 0;
}
Use Sparingly
goto can make code hard to follow. Prefer structured control flow
(loops, functions) in most cases. It's occasionally useful for cleanup code or
state machines.
Pattern Matching
Use regex in conditionals:
my str $input = "hello123";
if ($input =~ /[0-9]+/) {
say("Contains numbers");
}
if ($input !~ /^[0-9]+$/) {
say("Not purely numeric");
}
# Case-insensitive match
if ($input =~ /HELLO/i) {
say("Found hello (case-insensitive)");
}
Switch Statement
Use switch for multi-way branching:
my int $day = 3;
switch ($day) {
case 1 {
say("Monday");
}
case 2 {
say("Tuesday");
}
case 3 {
say("Wednesday");
}
default {
say("Other day");
}
}
No Fall-Through
Unlike C/Java, each
case is self-contained with braces.
There's no fall-through behavior and no break statement needed.
Switch with Strings
my str $color = "red";
switch ($color) {
case "red" {
say("Stop");
}
case "yellow" {
say("Caution");
}
case "green" {
say("Go");
}
default {
say("Unknown signal");
}
}
Alternative: Hash Dispatch
For dynamic dispatch or function tables, hashes work well:
my hash %day_names = {
"Mon" => "Monday",
"Tue" => "Tuesday",
"Wed" => "Wednesday"
};
my str $day = "Mon";
if (exists(%day_names, $day)) {
say($day_names{$day});
} else {
say("Unknown day");
}
Statement Modifiers
Perl-style postfix modifiers let you write concise one-liners:
# Postfix if/unless
say("hello") if $verbose;
say("warning") unless $quiet;
# Postfix while/until
$i = $i + 1 while $i < 10;
$i = $i + 1 until $i >= 10;
# Works with return, last, next, redo
return 0 if $error;
return $val unless $invalid;
last if $done;
next unless $valid;
Modifier Forms
EXPR if COND; is equivalent to if (COND) { EXPR; }.
EXPR unless COND; is equivalent to if (!COND) { EXPR; }.
EXPR while COND; is equivalent to while (COND) { EXPR; }.
EXPR until COND; is equivalent to while (!COND) { EXPR; }.
Short-Circuit Evaluation
# && and || short-circuit
my int $x = 0;
# Second expression not evaluated if first is false
$x && say("x is true");
# Second expression not evaluated if first is true
$x || say("x is false");
# Use for default values
my str $name = "";
my str $display = $name || "Anonymous";