Rust宏中的tt元变量类型是什么意思?

40

我正在阅读一本关于Rust的书,并开始尝试使用Rust宏。那里解释了所有元变量类型并提供了例子,除了最后一个 - tt。根据这本书的描述,它是“单个令牌树”。我很好奇,它是什么以及它用于什么?你能给个例子吗?

1个回答

61

这是一个用来确保在宏调用中所使用的()[]{}成对出现的概念。而tt将匹配任何单个标记或者任何成对的括号/方括号/大括号以及它们的内容。

例如,对于以下程序:

fn main() {
    println!("Hello world!");
}

标记树如下:

  • fn
  • main
  • ()
  • { println!("Hello world!"); }
    • println
    • !
    • ("Hello world!")
      • "Hello world!"
    • ;

每个标记都形成一棵树,其中简单的标记(例如fnmain等)是叶子节点,而被()[]{}包围的任何内容都有一个子树。请注意,(不会单独出现在标记树中:无法匹配没有相应)(

例如:

macro_rules! {
    (fn $name:ident $params:tt $body:tt) => { /* … */ }
}

使用$name → main$params → ()$body → { println!("Hello world!"); }可以匹配上述函数。

Token tree是最不严格的元变量类型:它可以匹配任何东西。它经常在宏中使用,其中有一个“不太关心”的部分,特别是在具有“头”和“尾”部分的宏中。例如,println!宏有一个分支匹配($fmt:expr, $($arg:tt)*),其中$fmt是格式字符串,$($arg:tt)*表示“所有其余内容”,并直接转发到format_args!。这意味着println!不需要知道实际格式并进行复杂的匹配。


3
为什么 println! 不使用 expr 呢?难道参数不都是表达式吗? - Tomas
5
@Tomas 不是仅限于使用 {} 中的位置参数,也可以使用命名参数如 foo=expr来替换所有的 "{foo}" - mcarton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接