loop / while / for
Rust loops: loop, while, for, labels, break with value, and iterator chaining.
Rust — loops
EXAMPLE
// ===== loop (infinite, break to exit) =====
let mut i = 0;
loop {
if i >= 5 { break; }
println!("{}", i);
i += 1;
}
// loop can RETURN a value through break:
let answer = loop {
if ready { break 42; }
};
// ===== while =====
let mut n = 5;
while n > 0 {
println!("{}", n);
n -= 1;
}
// ===== while let =====
let mut stack = vec![1, 2, 3];
while let Some(top) = stack.pop() {
println!("{}", top);
}
// ===== for over iterators =====
for x in 1..=10 { println!("{}", x); } // inclusive
for x in [1, 2, 3] { println!("{}", x); }
for x in &v { println!("{}", x); } // iter (borrow)
for x in v.iter() { println!("{}", x); } // same
for x in &mut v { *x *= 2; } // iter_mut
for (i, x) in v.iter().enumerate() { println!("{} {}", i, x); }
// ===== Iterator chains =====
let total: i32 = (1..=10).filter(|&x| x % 2 == 0).map(|x| x * x).sum();
let names: Vec<String> = users.iter().map(|u| u.name.clone()).collect();
// Lazy evaluation: iterators do nothing until consumed (collect / sum / for / count / etc).
// ===== Labels =====
'outer: for i in 0..10 {
for j in 0..10 {
if i * j > 50 {
break 'outer;
}
}
}
// continue 'label; also works.
// ===== break vs continue with value =====
let pos = (0..100).find(|x| x % 7 == 0 && x % 11 == 0); // Option<i32>
// ===== loop-like patterns from std =====
// Repeat N times:
for _ in 0..5 { do_thing(); }
// Forever, with break:
loop { /* ... */ if done { break; } }
// ===== Common pitfall: borrow inside loop =====
let mut v = vec![1, 2, 3];
// for x in &v { v.push(*x); } // ERROR: cannot borrow v as mutable
// Fix: collect needs first, or use indices.
let n = v.len();
for i in 0..n { v.push(v[i]); }
// ===== Iter methods you will use =====
// map / filter / take / skip / chain / zip / enumerate / rev
// any / all / find / position / count / sum / product / max / min
// fold / reduce / collect
// for_each (no return value)
// Example:
let sum: i32 = v.iter().take(5).sum();
let words: Vec<&str> = "a b c d".split_whitespace().collect();
let (evens, odds): (Vec<_>, Vec<_>) = (0..10).partition(|x| x % 2 == 0);
// ===== Patterns to internalise =====
// - for + iterators by default; while only for index-driven loops
// - while let / if let for Option / Result extraction in loops
// - Labels + break for exiting nested loops
// - Iterator chains beat manual indexing for clarity
// ===== Pitfalls =====
// - Borrowing the same value mutably and immutably in a loop -> compile error
// - Forgetting iterators are lazy (no work until collect / consume)
// - while true { ... } -> compiler suggests loop { ... }
// - Mutating a Vec while iterating its borrow -> compile error
Why it matters
Rust loops are expressive: loop with value, for over iterators, while let for pattern extraction, labels for breaking outer. Reach for iterator chains over manual indexing; the compiler enforces lifetime safety. Once iterators feel natural, the code reads close to functional.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
for i in 0..5 { println!("{i}"); }
let mut n = 0;
let result = loop {
n += 1;
if n == 10 { break n * 2; }
};
Try it Yourself »
Discussion
Loading…