Control Flow
Rust provides if/else, three loop forms (loop, while, for), and exhaustive match. Loops and branches can produce values when used as expressions.
Recipe
fn sum_evens(nums: &[i32]) -> i32 {
let mut total = 0;
for &n in nums {
if n % 2 == 0 {
total += n;
}
}
total
}
fn first_negative(nums: &[i32]) -> Option<i32> {
for &n in nums {
if n < 0 {
return Some(n);
}
}
None
}When to reach for this: Any branching or iteration. Prefer for over while with manual index when iterating collections.
Working Example
fn find_pair(target: i32, nums: &[i32]) -> Option<(usize, usize)> {
'outer: for i in 0..nums.len() {
for j in (i + 1)..nums.len() {
if nums[i] + nums[j] == target {
break 'outer (i, j);
}
}
}
}
fn retry<F: FnMut() -> bool>(mut f: F, max: u32) -> bool {
let mut attempts = 0;
loop {
if f() {
break true;
}
attempts += 1;
if attempts >= max {
break false;
}
}
}
fn main() {
let nums = [2, 7, 11, 15];
println!("{:?}", find_pair(9, &nums));
println!("{}", retry(|| false, 3));
}What this demonstrates:
- Labeled
break 'outerexits nested loops with a tuple value loopwith conditionalbreakimplements retry logic- Range
0..nums.len()for index-based access when needed Optionfor absent results instead of sentinel values
Deep Dive
Loop Forms
| Construct | Use |
|---|---|
for x in iter | Iterate collections, ranges, adapters |
while cond | Loop until condition is false |
loop | Infinite loop until break (can return value) |
let squares: Vec<i32> = (0..5).map(|n| n * n).collect();match Exhaustiveness
enum Color { Red, Green, Blue }
fn hex(c: Color) -> &'static str {
match c {
Color::Red => "#f00",
Color::Green => "#0f0",
Color::Blue => "#00f",
}
}Compiler errors if a variant is missing. Use _ only when you intentionally catch remaining cases.
if let and while let
let Some(x) = opt else { return };
while let Some(line) = lines.next() {
println!("{line}");
}Ergonomic partial matching without full match.
Gotchas
ifcondition not bool -if 1 { }fails. Fix: Use explicit comparisons.- Off-by-one ranges -
0..nexcludesn. Fix: Use0..=nfor inclusive end when needed. - Borrowing in
forloops -for item in &vecborrows;for item in vecmoves. Fix: Chooseiter(),iter_mut(), orinto_iter()deliberately. - Non-exhaustive
match- Adding enum variants breaks compiles. Fix: Treat as a feature; update all matches. breakvalue type mismatch - Allbreakin aloopmust return the same type. Fix: Annotate or unify types.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Iterator adapters | Transform/filter without explicit loop | Side effects need sequential clarity |
if let chain | Single-pattern checks | Many variants need match |
matches! macro | Boolean predicate on pattern | You need bound values |
| Recursion | Tree/graph structure | Deep stacks risk overflow |
FAQs
Can `for` loop over a reference?
Yes. for x in &vec borrows elements. for x in &mut vec mutably borrows.
How do I loop with an index?
for (i, v) in items.iter().enumerate() is idiomatic. Raw 0..len works when neighbors are needed.
What does `break` with a value do?
In loop, break 42 makes the loop expression evaluate to 42.
Can `while` return a value?
No. Only loop supports break value. Use loop or assign inside while.
What is `continue 'label`?
Skips to the next iteration of the labeled loop, like labeled break.
How do guards work in `match`?
match x { n if n > 0 => ..., _ => ... } adds a boolean condition to a pattern.
Is `switch` available?
No. Use match for exhaustive pattern matching.
Can I match on ranges?
Yes for integers and chars: 1..=5, 'a'..='z'.
What is loop `else`?
Not in Rust. Use break flags or Option return values instead.
How do I iterate a `HashMap`?
for (k, v) in &map or map.iter(). Order is arbitrary unless you use BTreeMap.
Related
- Functions & Expressions - expression-oriented blocks
- Pattern Matching with match - deep
matchpatterns - if let, let else & while let - partial matches
- Iterator Adapters - loop-free transforms
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.