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

Control Flow

Conditions take no parentheses, and braces are always required.

if

#![allow(unused)]
fn main() {
if hp <= 0 && !invincible {
    printLn("dead");
} else if invincible {
    printLn("cheat");
} else {
    printLn(`hp={hp}`);
}
}

if is also an expression. Used as a value, it needs a final else, and only the chosen arm runs:

#![allow(unused)]
fn main() {
let abs = if n < 0 { -n } else { n };
let tier = if xp > 500 { 3 } else if xp > 100 { 2 } else { 1 };
}

&& and || short-circuit.

while

#![allow(unused)]
fn main() {
let n = 3;
while n > 0 {
    n -= 1;
}
}

for

for walks a range or a collection. a..b stops before b; a..=b includes it.

#![allow(unused)]
fn main() {
for i in 0..5 { }          // 0 1 2 3 4
for i in 0..=5 { }         // 0 1 2 3 4 5
for n in xs { }            // each element of an array or slice
for i, n in xs { }         // with its index
}

break and continue work on the innermost loop. Put a label on a while or for to reach an outer one: break 'rows; leaves it, continue 'rows; moves to its next step. The defers of the loops left run first, innermost first.

#![allow(unused)]
fn main() {
'rows: for r in 0..3 {
    for c in 0..3 {
        if c == 1 { continue 'rows; }   // next row
        if r == 2 { break 'rows; }      // leave both loops
        printLn(`r{r} c{c}`);
    }
}
}

match

match must list every variant, each written with its enum name. There is no catch-all arm on an enum, so adding a variant to an enum points you at every match that needs it.

#![allow(unused)]
fn main() {
match dir {
    Dir.N { return "north"; }
    Dir.E { return "east"; }
    Dir.S { return "south"; }
    Dir.W { return "west"; }
}
}

Inside a payload, _ matches anything (Result.Err(_)). Payloads are covered in Enums and Errors.

match on an integer takes int literals or int consts as arms. It needs a final _ arm, and a repeated value is a compile error:

#![allow(unused)]
fn main() {
const MAX = 255;

match code {
    0 { printLn("zero"); }
    -1 { printLn("minus one"); }
    MAX { printLn("max"); }
    _ { printLn(`other {code}`); }
}
}

defer

defer runs a statement when its block ends, including on an early return. Several defers run last-first.

fn main() {
    let mem = Arena.create(16 * 1024 * 1024);
    defer mem.destroy();

    let frame = mem.checkpoint();
    defer mem.rewind(frame);    // runs before destroy
}