iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

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…