6 个版本

0.2.1 2023年7月19日
0.2.0 2023年7月19日
0.1.2 2020年7月4日
0.1.1 2020年7月4日
0.1.0 2020年7月4日

#1912 in 过程宏

Download history 206/week @ 2024-03-13 160/week @ 2024-03-20 174/week @ 2024-03-27 143/week @ 2024-04-03 128/week @ 2024-04-10 213/week @ 2024-04-17 267/week @ 2024-04-24 315/week @ 2024-05-01 285/week @ 2024-05-08 117/week @ 2024-05-15 196/week @ 2024-05-22 181/week @ 2024-05-29 136/week @ 2024-06-05 251/week @ 2024-06-12 157/week @ 2024-06-19 135/week @ 2024-06-26

每月下载量 703
8 个crate中(通过 defile)使用

Zlib 许可证

4KB

::defile

用于“解组”捕获的元变量(因此可能会破坏它们的卫生,因此得名)的辅助过程宏。

Repository Latest version Documentation MSRV unsafe forbidden License CI no_std

当使用需要使用特殊规则(例如 :expr:path:pat)进行解析的辅助 macro_rules 宏时,但后来还想进一步检查捕获的变量时,这很有用。

这并不是 macro_rules! 可以独自完成的事情,因为这些所谓的 元变量 被视为一个 不透明的 单个标记(捕获在元变量中的标记序列已被 分组(≈ 括号化),但使用了不可见的括号)。

示例

macro_rules! check_expr {
    (
        42
    ) => ({
        println!("Got `42`!");
    });

    (
        $($tt:tt)*
    ) => ({
        println!("Did not get `42`. Instead, got the following tokens:\n[");
        $(
            println!("    `{}`,", stringify!($tt));
        )*
        println!("]");
    });
}

macro_rules! check_all_exprs {(
    $(
        $expr:expr // use :expr to be able to use `,` as a delimiter
    ),* $(,)?
) => (
    fn main () {
        $(
            println!("vvvvvvvvvvvvv");
            check_expr!($expr);
            println!("^^^^^^^^^^^^^\n");
        )*
    }
)}

check_all_exprs!(42, 1 + 1);

输出

vvvvvvvvvvvvv
Did not get `42`. Instead, got the following tokens:
[
    `42`,
]
^^^^^^^^^^^^^

vvvvvvvvvvvvv
Did not get `42`. Instead, got the following tokens:
[
    `1 + 1`,
]
^^^^^^^^^^^^^
  • 那就是

    • 标记 42 不匹配 42

    • 话虽如此,表达式 1 + 1

      实际上,这正是这种行为的要点:如果我们执行 2 * $expr,其中 $expr 捕获 1 + 1

但通过执行

macro_rules! check_all_exprs {(
    $(
        $expr:expr // use :expr to be able to use `,` as a delimiter
    ),* $(,)?
) => (::defile::defile! { // 👈
    fn main () {
        $(
            println!("vvvvvvvvvvvvv");
            check_expr!(@$expr);
//                      👆
            println!("^^^^^^^^^^^^^\n");
        )*
    }
})}

我们确实得到

vvvvvvvvvvvvv
Got `42`!
^^^^^^^^^^^^^

vvvvvvvvvvvvv
Did not get `42`. Instead, got the following tokens:
[
    `1`,
    `+`,
    `1`,
]
^^^^^^^^^^^^^
  • 42 匹配了字面值 42,但请注意,这也导致 1 + 1 被拆分。因此,如果您要 defile 表达式,如 2 * @$expr,您可能不会得到预期的结果!请谨慎使用。

注意事项

目前(1.45.0),有关 macro_rules! 宏和过程宏之间交互的几个错误可能导致 defile! 和任何其他辅助过程宏拆分非 @ 前缀的组。

希望这些错误已经被解决,使得 defile! 的实际实现具有意义。

无运行时依赖