我使用库进行字符串实习(string-cache),它使用宏来高效创建元素(atom!
)。然而,为了简化,这里是一个类似的宏来演示问题
macro_rules! string_intern {
("d") => ("Found D");
}
说我需要从另一个宏调用这个宏并给它一个标识符的字符串版本。
macro_rules! print_ident {
($id:ident) => (
string_intern!(stringify!($id));
);
}
然而,调用此宏
fn main() {
print_ident!(d);
}
失败并显示错误:
error: no rules expected the token `stringify`
--> <anon>:7:24
|
7 | string_intern!(stringify!($id));
| ^^^^^^^^^
我知道stringify!
正确地将标识符d
转换为字符串"d"
,因为将其println!
提供给预期的工作。有没有办法将我想要转换为字符串的标识符传递给string_intern
?
答案 0 :(得分:9)
println!
允许您这样做,因为它使用了format_args!
封面,这是一个编译器提供的&#34;内在&#34;在使用之前强行评估其第一个参数。您无法从用户定义的宏执行此操作;你必须编写一个编译器插件(需要夜间编译器,不能保证稳定性)。
所以,是的;你不能。抱歉。你唯一能做的就是重新定义宏,使你不需要需要一个实际的字符串文字,或者改变你调用它的方式。
答案 1 :(得分:0)
您对string_intern!
的定义是期待文字"d"
而不是其他内容,但您传递的是这些令牌:stringify
,!
,...这就是为什么它失败。您想要的string_intern!
的定义可能是:
macro_rules! string_intern {
($e:expr) => {
match $e {
"d" => "Found D",
_ => "Not found",
}
}
}
,它可以接受任何求值为字符串类型的表达式。