Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Statements and Loops

Statements run actions and choose control flow.

Blocks group statements as the bodies of declarations and control-flow constructs, such as functions, if, loops, try, and using. Standalone { ... } and {} blocks are syntax errors, including inside another body.

Named functions, classes, interfaces, enums, global constants, type aliases, newtypes, imports, and file attributes belong at the top level of a file or namespace. They cannot appear inside function bodies or control-flow blocks. Use a closure when you need a function value inside a body.

Expression statements

Any expression may form a statement when followed by ;:

$value = 1;
$value++;
write_line!($value);

Discarding a value marked #[MustUse] raises an error. Use its result or pass it to discard! to state that you meant to ignore it.

Every expression statement needs an expression; ; alone is a syntax error.

Final locals

final binds a local once:

final $rate = 0.1;
final $price = 250.0;

assert!($price * $rate == 25.0);

The declaration must be the local’s first assignment. Any later write in the same function or file body is a compile error. A final local still follows normal value rules: an object may change through the local, but the local cannot point to another object.

if

An if condition must be bool:

$value = -3;
if ($value < 0) {
  $sign = 'negative';
} else if ($value == 0) {
  $sign = 'zero';
} else {
  $sign = 'positive';
}

assert!($sign == 'negative');

while and do ... while

while tests before each pass. do ... while runs its body once before the first test:

$count = 0;
while ($count < 3) {
  $count++;
}

do {
  $count--;
} while ($count > 0);

assert!($count == 0);

for

A for loop keeps its setup, condition, and step in one header:

$sum = 0;
for ($number = 1; $number <= 5; $number++) {
  $sum += $number;
}

assert!($sum == 15);

Each header section may hold a comma-separated expression list. An empty condition acts as true:

$left = 0;
$right = 3;
for (; $left < $right; $left++, $right--) {
  write_line!($left . ':' . $right);
}

foreach

foreach accepts an array, an Iterator<K, V>, or a ToIterator<K, V>:

$seen = vec[];
foreach (dict['a' => 1, 'b' => 2] as $key => $value) {
  $seen[] = $key . $value;
}

assert!($seen == vec['a1', 'b2']);

Omit the key when it is not needed. The value target may be a destructuring pattern.

Array iteration uses the entries present when the loop begins. Changing the source does not change that walk.

Variable scope

Each file body, function, method, and closure has its own variable scope. Control-flow blocks do not create another variable scope. A variable assigned on only some paths remains undefined when execution took another path.

Functions cannot read file-scope variables. A closure captures the outer variables it uses.