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
elseblock is executed - If the loop exits via a
breakstatement, theelseblock is not executed continuestatements work normally and do not affect theelseblock execution
§Examples
§Prime number search
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
passRust 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
forloops - Loop labels work normally for controlling nested loops
- Complex expressions in the iterable position may require parentheses due to Rust’s parsing rules