4. Control flow: everything is an expression
4.1 if, match, and blocks produce values
fn classify(status: u16) -> &'static str {
// `match` must be EXHAUSTIVE: the `_` arm is required here, because u16 has 65,536 values.
match status {
200 | 204 => "success",
301..=308 => "redirect",
400..=499 => "client error",
500..=599 => "server error",
_ => "unknown",
}
}
fn main() {
let n = 7;
let parity = if n % 2 == 0 { "even" } else { "odd" }; // no ternary; `if` is an expression
let squared = {
let t = n * n;
t + 0 // the last expression, with NO semicolon, is the block's value
};
println!("{parity} {squared} {}", classify(404));
}
4.2 Loops: loop, while, for, labels, and break with a value
fn main() {
// `loop` is an infinite loop that can return a value through `break`.
let mut attempts = 0;
let port = loop {
attempts += 1;
let candidate = 8000 + attempts;
if candidate % 3 == 0 {
break candidate; // the loop's value
}
};
// `for` iterates over anything that implements IntoIterator.
for i in 0..3 { print!("{i} "); } // 0 1 2 (0..=3 includes 3)
for (i, ch) in "héllo".char_indices() { print!("[{i}:{ch}]"); }
println!();
// Labels break out of nested loops; no goto needed (compare C §4.2).
'outer: for row in 0..10 {
for col in 0..10 {
if row * col == 42 {
println!("found at {row},{col}");
break 'outer;
}
}
}
println!("port={port} after {attempts} attempts");
}
4.3 if let, let else, and while let
These are shortcuts for a match where you care about one pattern:
fn parse_port(s: &str) -> u16 {
// let-else: bind on success, or the else block must leave the function (return/break/panic).
let Ok(port) = s.parse::<u16>() else {
return 8080;
};
port
}
fn main() {
let maybe_user: Option<&str> = Some("ada");
if let Some(name) = maybe_user {
println!("hello {name}");
}
let mut stack = vec![1, 2, 3];
while let Some(top) = stack.pop() { // runs until pop() returns None
print!("{top} ");
}
println!("{} {}", parse_port("443"), parse_port("http"));
}
let else is the Rust version of Go's if err != nil { return } guard
clause. It keeps the main path unindented.