我试图制作一个我可以通过以下方式调用的宏:
mactest!(some::Path[1, 2, AnotherName[3, 4]])
这相当于以下内容:
make_result(
"some::Path",
1.convert(),
2.convert(),
make_result(
"AnotherName",
3.convert(),
4.convert()
)
)
其中convert
是将为一堆类型实现的某些特征。 (convert
和make_result
具有相同的结果类型。)
就我而言:
// Note: u32 is used as an example result type.
// The real code attempts to create a more complicated object.
trait Foo {
fn convert(&self) -> u32;
}
fn make_result(name: &str, data: Vec<u32>) -> u32 {
// This example ignores name and makes a meaningless result
data.iter().fold(0,|a, &b| a + b)
}
#[macro_export]
macro_rules! mactest {
( [ $($inner:expr),* ] ) => {{
let mut result = Vec::new();
$(
// Process each element.
result.push(mactest!($inner));
)*
result
}};
($name:path [ $($inner:tt),* ] ) => {
make_result(stringify!($name), mactest!([$($inner),*]))
};
($name:ident [ $($inner:tt),* ] ) => {
make_result(stringify!($name), mactest!([$($inner),*]))
};
// Process single value. This is never matched?
($x:expr) => {
$x.convert()
};
}
宏的第一个匹配分支应该与列表中的每个元素匹配到最后的path/ident[items]
或单个项.convert
分支。但是从未达到最终分支,当单个项目进入宏时,生锈抱怨error: expected ident, found '1'
,即mactest!(1)
。
我作为初学者生锈用户的理由是宏有四种模式:[expr*]
,path[tt*]
,ident[tt*]
和expr
。当我将1之类的内容传递给宏时,我不明白为什么上述任何模式都应该匹配/干扰。
有人可以解释为什么这不起作用吗?是否有解决方法来获得预期的结果?
答案 0 :(得分:0)
从第一个开始并从那里开始尝试宏规则。因此,如果您想在特殊情况下阻止其他规则触发,则需要先设置特殊情况规则。