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日 |
#631 in Rust 模式
每月 702 次下载
用于 7 个 包 (直接使用 2 个)
11KB
::defile
辅助过程宏,用于将捕获的宏元变量“取消分组”(因此可能会破坏它们的卫生,所以命名为“取消分组”)。
这在使用需要使用特殊规则(例如 :expr
、:path
、:pat
)进行解析的辅助宏时非常有用,但这些宏随后还想进一步检查捕获的变量。
这不可能由 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
,我们期望结果为2 * (1 + 1)
,而不是2 * 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!
宏和过程宏之间交互的bug,可能会导致 defile!
和任何其他辅助过程宏将非 @
-前缀的组分割。
希望这些bug已经解决,使得 defile!
的实际实现变得有意义。