订购宏参数执行

时间:2016-10-02 12:15:33

标签: macros rust

我使用库进行字符串实习(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));
  |                        ^^^^^^^^^

Playground link

我知道stringify!正确地将标识符d转换为字符串"d",因为将其println!提供给预期的工作。有没有办法将我想要转换为字符串的标识符传递给string_intern

2 个答案:

答案 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",
        }
    }
}

,它可以接受任何求值为字符串类型的表达式。