for_in_ifs

Macro for_in_ifs 

Source
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 inif外,不会引入任何其它开销
  • 具体应用可见列表推导式宏[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)]);