21.13 if let
and while let
: Concise Conditional Matching
When you only care about matching one specific pattern and ignoring the rest, a full match
can be verbose. if let
and while let
provide more concise alternatives.
21.13.1 if let
Handles a single refutable pattern. Executes the block if the pattern matches. Can optionally have an else
block for the non-matching case.
fn main() { let config_value: Option<i32> = Some(5); // Using if let if let Some(value) = config_value { println!("Config value is: {}", value); } else { println!("Config value not set."); } let error_code: Result<u32, &str> = Err("Network Error"); if let Ok(data) = error_code { // This block is skipped println!("Operation succeeded: {}", data); } else { println!("Operation failed."); // This block runs } }
21.13.2 while let
Creates a loop that continues as long as the pattern matches the value produced in each iteration (commonly from an iterator or repeated function call).
fn main() { let mut tasks = vec![Some("Task 1"), None, Some("Task 2"), Some("Task 3")]; // Process tasks from the end using pop() which returns Option<T> while let Some(task_option) = tasks.pop() { // Pattern: Some(task_option) if let Some(task_name) = task_option { // Nested Pattern: Some(task_name) println!("Processing: {}", task_name); } else { println!("Skipping empty task slot."); } } println!("Finished processing tasks."); // Example output order: Task 3, Task 2, Skipping empty task slot, Task 1 // More direct with `while let Some(Some(..))` pattern: let mut data_stream = vec![Some(10), Some(20), None, Some(30)].into_iter(); // The loop runs as long as `next()` returns `Some(Some(value))` while let Some(Some(value)) = data_stream.next() { println!("Received value: {}", value); // Outputs 10, 20, 30 } println!("End of stream."); }