我正在阅读一本关于Rust的书,并开始尝试使用Rust宏。那里解释了所有元变量类型并提供了例子,除了最后一个 - tt
。根据这本书的描述,它是“单个令牌树”。我很好奇,它是什么以及它用于什么?你能给个例子吗?
我正在阅读一本关于Rust的书,并开始尝试使用Rust宏。那里解释了所有元变量类型并提供了例子,除了最后一个 - tt
。根据这本书的描述,它是“单个令牌树”。我很好奇,它是什么以及它用于什么?你能给个例子吗?
这是一个用来确保在宏调用中所使用的()
、[]
和{}
成对出现的概念。而tt
将匹配任何单个标记或者任何成对的括号/方括号/大括号以及它们的内容。
例如,对于以下程序:
fn main() {
println!("Hello world!");
}
标记树如下:
fn
main
()
{ println!("Hello world!"); }
println
!
("Hello world!")
"Hello world!"
;
每个标记都形成一棵树,其中简单的标记(例如fn
、main
等)是叶子节点,而被()
、[]
或{}
包围的任何内容都有一个子树。请注意,(
不会单独出现在标记树中:无法匹配没有相应)
的(
。
例如:
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!
不需要知道实际格式并进行复杂的匹配。
println!
不使用expr
呢?难道参数不都是表达式吗? - Tomas{}
中的位置参数,也可以使用命名参数如foo=expr
来替换所有的"{foo}"
。 - mcarton