【发布时间】:2016-07-10 15:36:26
【问题描述】:
我正在尝试制作一个可以通过以下方式调用的宏:
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)。
作为 rust 初学者,我的理由是宏有四种模式:[expr*]、path[tt*]、ident[tt*] 和 expr。当我将类似 1 的内容传递给宏时,我不明白为什么上述任何模式都应该匹配/干扰。
有人可以解释为什么这不起作用吗?是否有解决方法来获得预期的结果?
【问题讨论】:
-
您的宏在常规情况下不起作用:play.rust-lang.org/…。它抱怨“应为
.、]或操作员之一,发现,”