macro_rules! for_in_ifs {
{ { $($code:tt)* } } => { ... };
{
$code:tt
// `for-in-if-let`主体
$($tag:lifetime :)? for $i:pat in ($iter:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
if let $p:pat = ($cond:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
// 剩余部分
$($tail:tt)*
} => { ... };
{
$code:tt
// `for-in-if`主体
$($tag:lifetime :)? for $i:pat in ($iter:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
if ($cond:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
// 剩余部分
$($tail:tt)*
} => { ... };
{
$code:tt
// `for-in`主体
$($tag:lifetime :)? for $i:pat in ($iter:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
// 剩余部分
$($tail:tt)*
} => { ... };
{
$code:tt
// `while-let-if-let`主体
$($tag:lifetime :)? while let $i:pat = ($iter:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
if let $p:pat = ($cond:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
// 剩余部分
$($tail:tt)*
} => { ... };
{
$code:tt
// `while-let-if`主体
$($tag:lifetime :)? while let $i:pat = ($iter:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
if ($cond:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
// 剩余部分
$($tail:tt)*
} => { ... };
{
$code:tt
// `while-let`主体
$($tag:lifetime :)? while let $i:pat = ($iter:expr) // ⚠️ 此处可以使用`:tt`,但编译器会发警告(不必要的括号)
// 剩余部分
$($tail:tt)*
} => { ... };
}Expand description
for-in-if格式
- 🎯使用类似「列表推导式」的方式组织
for循环代码 - ✨支持类似「列表推导式」的语法,但能在其中运行代码块
- ⚡基本是零成本抽象:除了
for in与if外,不会引入任何其它开销 - 具体应用可见列表推导式宏[
list]
§用例与测试
use nar_dev_utils::{for_in_ifs};
// 创建可复用的数组
let mut v = vec![];
// 循环向数组添加元素
for_in_ifs! {
{
// ✨可在循环中执行任意代码,就好像它本来就在for循环中一样
let tuple = (i, j);
v.push(tuple);
}
for i in (1..10)
for j in (1..10) if (i + j < 4) // ✨支持条件判断
for k in (1..10) if let -1..=1 = (k) // ✨支持带`let`的条件判断
}
// 检验 #1
assert_eq!(v, [(1, 1), (1, 2), (2, 1)]);
v.clear();
for_in_ifs! {
{
// ✨可以在循环中使用控制语句
// * ⚠️默认只作用于最内层
// * 📄亦即此处`continue 'j`与`continue`等价
if j > 2 { continue 'j; }
// * 🚩此`break`导致`(2, 1)`被删去
if i > 1 { break 'i; }
v.push((i, j));
}
// ✨支持设置循环标签
'i: for i in (1..10) // * ✨标签语法和普通for如出一辙
'j: for j in (1..10)
}
// 检验 #2
assert_eq!(v, [(1, 1), (1, 2)]);
v.clear();
let mut iter1 = 1..10;
let mut n = 0;
let mut iter2 = std::iter::from_fn(move || {
// 简单的闭包迭代器
n += 1;
match n {
..=9 => Some(n),
_ => None,
}
});
let mut iter3 = iter1.clone();
for_in_ifs! {
{
if i > 1 { break 'i; }
v.push((i, j));
break 'k; // * * 🚩此`break`导致对`iter3`无法在内层被迭代完,制止了重复与提前结束
}
// ✨支持设置循环标签
'i: while let Some(i) = (iter1.next()) // * ✨支持`while let`语法
while let Some(j) = (iter2.next()) if (j <= 2)
'k: while let Some(k) = (iter3.next()) if let 0..=2 = (k)
}
// 检验 #3
assert_eq!(v, [(1, 1), (1, 2)]);