Я читаю книгу о Rust и начинаю играть с Rust macros. Здесь описываются все метапарабельные типы, и есть примеры, кроме последнего - tt. Согласно книге, это "единственное дерево-маркер". Мне любопытно, что это такое и для чего он используется? Можете ли вы привести пример?
Что означает метастабильный тип tt в макросах Rust?
Ответ 1
Это понятие введено, чтобы гарантировать, что все, что находится в вызове макроса, правильно соответствует парам (), [] и {}. tt сопоставляет любой токен или любую пару скобок/скобок/скобок с их содержанием.
Например, для следующей программы:
fn main() {
println!("Hello world!");
}
Токен-деревья будут:
fnmain()- ∅
{ 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!"); }.
Дерево токенов - это наименее требовательный тип метавариабельной переменной: он соответствует чему угодно. Он часто используется в макросах, в которых есть "не очень важно", особенно в макросах, в которых есть "голова" и "хвост". Например, макросы println! имеют ветвь, совпадающую с ($fmt:expr, $($arg:tt)*), где $fmt - строка формата, а $($arg:tt)* означает "все остальное" и просто пересылается в format_args!. Это означает, что println! не нужно знать фактический формат и выполнять сложное сопоставление с ним.