</>
Skip to content
Rust lessons (14/43)

Rust — Loops

Three kinds of loops

Rust provides three loop keywords:

LoopUse case
loopInfinite loop — break out manually
whileConditional loop — runs while a condition is true
forIterator loop — runs for each item in a sequence

Each serves a distinct purpose. Rust has no do-while — loop covers that pattern.

The loop keyword

loop creates an infinite loop that runs until you break:

fn main() {
    let mut count = 0;

    loop {
        count += 1;
        println!("Count: {}", count);

        if count >= 5 {
            break;
        }
    }
}

Output:

Count: 1
Count: 2
Count: 3
Count: 4
Count: 5

break exits the loop. Without it, the loop runs forever.

loop returns a value

Unlike loops in most languages, Rust's loop can return a value:

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2;  // returns 20
        }
    };

    println!("Result: {}", result);  // 20
}

The value after break becomes the loop's result. This is useful for searching or retrying until a condition is met.

Nested loops with labels

When loops are nested, break only exits the innermost loop. Use labels to break out of a specific loop:

fn main() {
    let mut count = 0;

    'outer: loop {
        let mut remaining = 10;

        loop {
            if remaining == 9 {
                break;  // exits inner loop
            }
            if count == 2 {
                break 'outer;  // exits outer loop
            }
            remaining -= 1;
        }

        count += 1;
    }

    println!("Count: {}", count);  // 2
}

Labels start with a single quote 'name and appear before the loop. Use break 'label to exit that specific loop.

The while loop

A while loop runs as long as a condition is true:

fn main() {
    let mut number = 5;

    while number > 0 {
        println!("{}!", number);
        number -= 1;
    }

    println!("Liftoff!");
}

Output:

5!
4!
3!
2!
1!
Liftoff!

while checks the condition before each iteration. If the condition is false initially, the loop never runs.

Avoiding while loops for iteration

Don't use while with a counter for simple iteration — use for instead:

// Works but not idiomatic
let mut i = 0;
while i < 5 {
    println!("{}", i);
    i += 1;
}

// Idiomatic — use for
for i in 0..5 {
    println!("{}", i);
}

for is safer — no off-by-one errors, no forgotten increments, and the compiler optimizes it better.

The for loop

for iterates over anything that implements the Iterator trait:

fn main() {
    // Range iteration
    for i in 0..5 {
        println!("{}", i);
    }

    // Inclusive range
    for i in 1..=5 {
        println!("{}", i);
    }

    // Iterating over an array
    let fruits = ["apple", "banana", "cherry"];
    for fruit in fruits {
        println!("{}", fruit);
    }

    // Iterating with index
    for (index, fruit) in fruits.iter().enumerate() {
        println!("{}. {}", index + 1, fruit);
    }
}

The for loop is Rust's primary iteration tool. It handles ranges, arrays, vectors, strings, files, and any custom iterator.

Iterator methods

Rust's iterators are powerful — chain methods for filtering, mapping, and collecting:

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // Filter even numbers, double them, collect into a new vector
    let result: Vec<i32> = numbers
        .iter()
        .filter(|&&x| x % 2 == 0)
        .map(|&x| x * 2)
        .collect();

    println!("{:?}", result);  // [4, 8, 12, 16, 20]
}

Iterators are lazy — they compute values on demand. .collect() triggers the computation and builds the final collection.

break and continue

break exits the loop entirely:

for i in 0..100 {
    if i == 5 {
        break;
    }
    println!("{}", i);
}
// Prints: 0 1 2 3 4

continue skips to the next iteration:

for i in 0..10 {
    if i % 2 == 0 {
        continue;  // skip even numbers
    }
    println!("{}", i);
}
// Prints: 1 3 5 7 9

Both work with labeled loops — break 'outer and continue 'outer.

Common loop patterns

Accumulator

fn main() {
    let numbers = vec![10, 20, 30, 40, 50];
    let mut sum = 0;

    for num in &numbers {
        sum += num;
    }

    println!("Sum: {}", sum);  // 150
}

Search with loop

fn main() {
    let haystack = vec![3, 7, 1, 9, 4, 6];
    let needle = 9;

    let mut found = None;
    for (i, &val) in haystack.iter().enumerate() {
        if val == needle {
            found = Some(i);
            break;
        }
    }

    match found {
        Some(index) => println!("Found {} at index {}", needle, index),
        None => println!("Not found"),
    }
}

Retry with loop

fn main() {
    let mut attempts = 0;

    let password = loop {
        attempts += 1;
        println!("Attempt {} — enter password:", attempts);

        // Simulate input
        let input = "secret";

        if input == "secret" {
            break "Access granted";
        }

        if attempts >= 3 {
            break "Access denied";
        }
    };

    println!("{}", password);
}

Infinite loops in real code

loop with break is the standard pattern for event loops, servers, and games:

fn main() {
    // Simulated event loop
    let events = vec!["click", "scroll", "resize", "quit"];

    for event in events {
        match event {
            "quit" => {
                println!("Shutting down");
                break;
            }
            other => println!("Handling: {}", other),
        }
    }
}

Mini Practice

  1. Use loop to calculate factorials — break when you reach 10!
  2. Print the first 20 Fibonacci numbers using a for loop
  3. Use while to simulate a countdown from 10 to 0, printing "Liftoff!" at the end
  4. Iterate over a vector and print only elements greater than 5 using continue
  5. Use a labeled loop to find the first pair of numbers that multiply to 30

Next: functions — reusable code blocks →

Related Topics

Frequently Asked Questions about Loops

What is Loops in Rust?

Loops is a fundamental concept in Rust. This lesson explains it step by step with clear examples, making it easy for beginners to understand.

How do I learn Loops?

Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Loops.

Why is Loops important in Rust?

Loops is essential for Rust development. Understanding this concept will help you write better code and solve real-world problems more effectively.