for_

Macro for_ 

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

The for_! procedural macro with enhanced loop control.

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

§Syntax

for_! { variable in iterable {
    // loop body
} else {
    // else block
}}

// With optional label:
for_! { 'label: variable in iterable {
    // loop body
} else {
    // else block
}}

§Behavior

  • The loop iterates over all elements in the iterable
  • If the loop completes by exhausting all elements, 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

use for_else::for_;

fn is_prime(n: u32) -> bool {
    if n <= 1 { return false; }
    for i in 2..n {
        if n % i == 0 { return false; }
    }
    true
}

for_! { n in 2100..=2110 {
    if is_prime(n) {
        println!("Found prime: {}", n);
        break;
    }
} else {
    println!("No prime numbers found in range");
}}

§Finding an element in a collection

use for_else::for_;

fn find_user(users: &[&str], target: &str) -> bool {
    for_! { user in users {
        if *user == target {
            println!("Found user: {}", user);
            return true;
        }
    } else {
        println!("User '{}' not found", target);
    }}
    false
}

let users = ["alice", "bob", "charlie"];
find_user(&users, "dave");  // Prints: User 'dave' not found

§Validation with early exit

use for_else::for_;

fn validate_data(numbers: &[i32]) -> bool {
    for_! { &num in numbers {
        if num < 0 {
            println!("Invalid negative number found: {}", num);
            return false;
        }
        if num > 100 {
            println!("Number too large: {}", num);
            return false;
        }
    } else {
        println!("All numbers are valid");
        return true;
    }}
    false
}

§Working with complex expressions

use for_else::for_;

struct DataSource;
impl DataSource {
    fn items(&self) -> impl Iterator<Item = i32> {
        vec![1, 2, 3, 4, 5].into_iter()
    }
}

// Note: Complex expressions may need parentheses
for_! { item in (DataSource {}).items() {
    if item > 10 {
        println!("Found large item: {}", item);
        break;
    }
} else {
    println!("No large items found");
}}

§Nested loops with labels

Labels should be put inside the macro

use for_else::for_;

for_! { 'outer: i in 0..3 {
    for_! { j in 0..3 {
        if i == 1 && j == 1 {
            break 'outer;  // Break outer loop
        }
        println!("({}, {})", i, j);
    } else {
        println!("Inner loop {} completed", i);
    }}
} else {
    println!("Both loops completed naturally");
}}

§Comparison with Python

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

Python:

for item in iterable:
    # loop body
    if some_condition:
        break
else:
    # executed if loop completed without break
    pass

Rust with for_!:

for_! { item in iterable {
    // loop body
    if some_condition {
        break;
    }
} else {
    // executed if loop completed without break
}}

§Notes

  • The macro supports all the same iterables as standard for loops
  • Loop labels work normally for controlling nested loops
  • Complex expressions in the iterable position may require parentheses due to Rust’s parsing rules