I'm reading a book about Rust, and start playing with Rust macros. All metavariable types are explained there and have examples, except the last one – tt. According to the book, it is a “a single token tree”. I'm curious, what is it and what is it used for? Can you please provide an example?
- 3,379
- 3
- 28
- 41
1 Answers
That's a notion introduced to ensure that whatever is in a macro invocation correctly matches (), [] and {} pairs. tt will match any single token or any pair of parenthesis/brackets/braces with their content.
For example, for the following program:
fn main() {
println!("Hello world!");
}
The token trees would be:
fnmain()- ∅
{ println!("Hello world!"); }println!("Hello world!")"Hello world!"
;
Each one forms a tree where simple tokens (fn, main etc.) are leaves, and anything surrounded by (), [] or {} has a subtree. Note that ( does not appear alone in the token tree: it's not possible to match ( without matching the corresponding ).
For example:
macro_rules! {
(fn $name:ident $params:tt $body:tt) => { /* … */ }
}
would match the above function with $name → main, $params → (), $body → { println!("Hello world!"); }.
Token tree is the least demanding metavariable type: it matches anything. It's often used in macros which have a “don't really care” part, and especially in macros which have a “head” and a “tail” part. For example, the println! macros have a branch matching ($fmt:expr, $($arg:tt)*) where $fmt is the format string, and $($arg:tt)* means “all the rest” and is just forwarded to format_args!. Which means that println! does not need to know the actual format and do complicated matching with it.
- 27,633
- 5
- 85
- 95
-
3Why would `println!` not use `expr` instead? Aren't the parameters all expressions? – Tomas Jul 21 '18 at 21:38
-
5@Tomas no, they can also be [named parameters like `foo=expr`](https://doc.rust-lang.org/std/fmt/index.html#named-parameters) to replace all the `"{foo}"`s. – mcarton Jul 21 '18 at 22:24