What does the tt metavariable type mean in Rust macros?

后端 未结 1 1002
北恋
北恋 2020-12-06 09:38

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. Acco

相关标签:
1条回答
  • 2020-12-06 10:20

    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:

    • fn
    • main
    • ()
    • { 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.

    0 讨论(0)
提交回复
热议问题