← Back to Rust Course | Chapter 8: Enums & Pattern Matching | Lesson 5 of 7

while let Syntax

while let keeps repeating an action for as long as a value keeps matching the pattern you care about.
Syntax
rust
while let Pattern(binding) = expression {
    // body
}

Basic while let

while let repeats its block for as long as the given pattern keeps matching the value, checked fresh at the start of every iteration.

Example: Basic while let

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare a mutable variable `stack`, initialized to `vec![1, 2, 3]`
    let mut stack = vec![1, 2, 3];
    // Keep looping while `let Some(top) = stack.pop()` holds
    while let Some(top) = stack.pop() {
        // Print "Popped: {}" to the console, substituting in `top` (with a trailing newline)
        println!("Popped: {}", top);
    }
}

Draining a Queue-like Structure

while let is especially handy for repeatedly pulling items from a structure until it is empty, since .pop() naturally returns None once nothing is left.

Example: Draining a Queue-like Structure

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare a mutable variable `queue`, initialized to `vec!["a", "b", "c"]`
    let mut queue = vec!["a", "b", "c"];
    // Keep looping while `let Some(item) = queue.pop()` holds
    while let Some(item) = queue.pop() {
        // Print "Processing: {}" to the console, substituting in `item` (with a trailing newline)
        println!("Processing: {}", item);
    }
    // Print "Queue is now empty" to the console (with a trailing newline)
    println!("Queue is now empty");
}

while let With a Custom Enum

while let works with any enum pattern, not just Option, as long as each iteration produces a new value to test against the pattern.

Example: while let With a Custom Enum

markup
// Define an enum `Fetch` listing its possible variants
enum Fetch {
    Item(i32),
    Empty,
}

// Entry point: execution of the program starts here
fn main() {
    // Declare a mutable variable `values`, initialized to `vec![10, 20, 30]`
    let mut values = vec![10, 20, 30];
    // Declare a mutable variable `next`, initialized to `|| values.pop().map_or(Fetch::Empty, Fetch::Item)`
    let mut next = || values.pop().map_or(Fetch::Empty, Fetch::Item);
    // Keep looping while `let Fetch::Item(v) = next()` holds
    while let Fetch::Item(v) = next() {
        // Print "Got item: {}" to the console, substituting in `v` (with a trailing newline)
        println!("Got item: {}", v);
    }
}

Comparing to a Manual loop

Without while let, the same logic requires a loop combined with a match and an explicit break in the None arm -- while let expresses this common pattern far more concisely.

Example: Comparing to a Manual loop

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare a mutable variable `stack`, initialized to `vec![5, 10]`
    let mut stack = vec![5, 10];
    // Loop forever until an explicit `break`
    loop {
        // Match on `stack.pop()` and branch by pattern
        match stack.pop() {
            Some(v) => println!("value: {}", v),
            None => break,
        }
    }
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Forgetting the loop stops automatically the first time the pattern no longer matches -- no manual break is needed for that.
  2. Using while let on a collection when a plain for loop would be simpler and more idiomatic.
  3. Not realizing .pop() on a Vec returns an Option, which is exactly the shape while let Some(x) = ... is designed to consume.
Chapter Summary
  • while let pattern = value { ... } loops as long as value continues to match the given pattern.
  • It commonly pairs with methods returning Option, like Vec::pop(), to process items until none remain.
  • The loop exits automatically the first time the match fails, with no explicit break required for that case.
  • while let reduces boilerplate compared to a manual loop with a match and break inside.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.