我写了一个简单的宏:
macro_rules! my_macro {
{
f($x:expr, $y:expr, $z:expr);
$($c:expr => {
$($m:expr => {
$($s:expr => $b:expr),+
}),+
}),+
} => {{
match ($x, $y, $z) {
$(
($c, $m, $s => $b),
)+
}
}};
}
fn main(){
let c = 0;
let m = 0;
let s = 0;
my_macro! {
f (c, m, s);
cc => {
mm => {
ss => b
}
}
}
}
并得到编译器错误:
error: variable 'm' is still repeating at this depth
--> project/src/mod.rs
|
39 | ($c, $m, $s => $b),
| ^^^^^^^
我不完全理解为什么会这样。 为什么以及如何修复?
答案 0 :(得分:0)
在您的宏规则中,
f($x:expr, $y:expr, $z:expr);
$($c:expr => {
$($m:expr => {
$($s:expr => $b:expr),+
}),+
}),+
$x
,$y
和$z
绑定单个expr
。但是,绑定了$c
的整个列表。此外,与每个$c
关联的是$m
的整个列表,因为$m
仍在与$(...).+
关联的$c
块内。对于这些$m
中的每一个,都绑定了$s
s的整个列表。
现在在您的输出中,
{{
match ($x, $y, $z) {
$(
($c, $m, $s => $b),
)+
}
}};
您只能使用$(...)+
打开一层列表。一层之后,$m
仍然是表达式列表(“重复”),因此不能直接使用。请记住,$m
实际上是列表列表(因为每个$m
都有一个$c
列表),$s
实际上是列表列表的列表。
您要么需要重组规则,以便每个$m
仅一个$s
和一个$c
(都在一个$(...),+
中),或者您需要重组输出,以使$m
和$s
被解压缩适当的次数。
尝试第一种方法(输入规则中的单个$(...),+
)后,我建议采用$c
,$m
和$s
模式,而不要使用表达式(如(而不是$c: pat
中的$c: expr
中)。这样一来,它们就可以在比赛分支的左侧使用。
macro_rules! my_macro {
{
f($x:expr, $y:expr, $z:expr);
$($c:pat => {
$m:pat => {
$s:pat => $b:expr
}
}),+
} => {
match ($x, $y, $z) {
$(
($c, $m, $s) => $b,
)+
}
};
}
真正的解决方案在很大程度上取决于您要完成的工作。