while_

Macro while_ 

Source
while_!() { /* proc-macro */ }
Expand description

The while_! procedural macro with enhanced loop control.

This macro is an extension of the standard while loop in Rust. It allows users to have an additional else block that executes if the loop completed without encountering a break statement.

§Syntax

while_! { condition {
    // loop body
} else {
    // else block
}}

// With optional label:
while_! { 'label: condition {
    // loop body
} else {
    // else block
}}

§Notes

  • The macro supports all the same conditions as standard while loops
  • Loop labels work normally for controlling nested loops
  • Complex expressions in the condition position are fully supported

§Behavior

  • The loop continues to execute as long as the condition evaluates to true
  • If the loop exits naturally (condition becomes false), the else block is executed
  • If the loop exits via a break statement, the else block is not executed
  • continue statements work normally and do not affect the else block execution

§Examples

§Basic usage

use for_else::while_;

let mut count = 0;
let mut found = false;

while_! { count < 5 {
    if count == 10 {  // This condition is never true
        found = true;
        break;
    }
    count += 1;
} else {
    println!("Loop completed without finding target value");
}}

assert!(!found);  // Loop completed naturally, else block executed

§Search with early termination

use for_else::while_;

fn find_target(data: &[i32], target: i32) -> Option<usize> {
    let mut index = 0;
    let mut result = None;
     
    while_! { index < data.len() {
        if data[index] == target {
            result = Some(index);
            break;  // Found it, exit early
        }
        index += 1;
    } else {
        println!("Target {} not found in data", target);
    }}
     
    result
}

§Retry mechanism with timeout

use for_else::while_;
use std::time::{Duration, Instant};

fn retry_operation() -> bool {
    let start = Instant::now();
    let timeout = Duration::from_secs(5);
     
    while_! { start.elapsed() < timeout {
        if attempt_operation() {
            println!("Operation succeeded!");
            return true;
        }
        std::thread::sleep(Duration::from_millis(100));
    } else {
        println!("Operation timed out after 5 seconds");
    }}
     
    false
}

fn attempt_operation() -> bool {
    // Some operation that might succeed or fail
    false
}

§Nested loops with labels

Labels should be put inside the macro

use for_else::while_;

let mut found_target = false;
let mut outer_count = 0;

while_! { 'outer: outer_count < 5 {
    let mut inner_count = 0;
    while_! { inner_count < 5 {
        if outer_count == 2 && inner_count == 3 {
            println!("Found target at ({}, {})", outer_count, inner_count);
            found_target = true;
            break 'outer;  // Break outer loop
        }
        inner_count += 1;
    } else {
        println!("Inner loop completed for outer_count = {}", outer_count);
    }}
    outer_count += 1;
} else {
    println!("Search completed without early termination");
}}

assert!(found_target);

§Comparison with Python

This macro brings Python-like while-else behavior to Rust:

Python:

while condition:
    # loop body
    if some_condition:
        break
else:
    # executed if loop completed without break
    pass

Rust with while_!:

while_! { condition {
    // loop body
    if some_condition {
        break;
    }
} else {
    // executed if loop completed without break
}}