Что означает символ @ в декларативном макросе?
Я видел @
символ используется в макросах, но я не могу найти упоминания о нем в Rust Book или в любой официальной документации или сообщениях в блоге. Например, в этом ответе переполнения стека он используется так:
macro_rules! instructions {
(enum $ename:ident {
$($vname:ident ( $($vty: ty),* )),*
}) => {
enum $ename {
$($vname ( $($vty),* )),*
}
impl $ename {
fn len(&self) -> usize {
match self {
$($ename::$vname(..) => instructions!(@count ($($vty),*))),*
}
}
}
};
(@count ()) => (0);
(@count ($a:ty)) => (1);
(@count ($a:ty, $b:ty)) => (2);
(@count ($a:ty, $b:ty, $c:ty)) => (3);
}
instructions! {
enum Instruction {
None(),
One(u8),
Two(u8, u8),
Three(u8, u8, u8)
}
}
fn main() {
println!("{}", Instruction::None().len());
println!("{}", Instruction::One(1).len());
println!("{}", Instruction::Two(1, 2).len());
println!("{}", Instruction::Three(1, 2, 3).len());
}
В результате использования выясняется, что он используется для объявления другого макроса, который является локальным по отношению к основному.
Что означает этот символ и почему вы используете его, а не просто создаете другой макрос верхнего уровня?
1 ответ
В части макроса, совпадающей с шаблоном, символы могут означать то, что автор хочет, чтобы они имели в виду. Ведущий символ @
часто используется для обозначения "детали реализации" макроса - части макроса, которую внешний пользователь не должен использовать.
В этом примере я использовал его для сопоставления с образцом параметров кортежа, чтобы получить количество параметров кортежа.
Помимо макросов, @
Символ используется для сопоставления с шаблоном при назначении имени всему шаблону:
match age {
x @ 0 => println!("0: {}", x),
y @ 1 => println!("1: {}", y),
z => println!("{}", z),
}
С некоторой растяжкой эту же логику можно применить к использованию в макросе - мы сопоставляем шаблон с кортежем, но также прикрепляем имя к этому конкретному шаблону. Я думаю, что я даже видел, как люди используют что-то еще более параллельное: (count @ ...
, Тем не менее, "Маленькая книга макросов ржавчины" указывает:
Причина использования
@
является то, что с Rust 1.2,@
токен не используется в позиции префикса; как таковой, он не может конфликтовать ни с чем. Другие символы или уникальные префиксы могут использоваться по желанию, но использование@
начал широко распространяться, поэтому его использование может помочь читателям понять ваш код.
а не просто создание другого макроса верхнего уровня
Создание другого макроса, вероятно, является лучшей практикой, но только в современном Rust. До недавних изменений в Rust, которые позволили вам импортировать макросы напрямую, иметь несколько макросов было непросто для конечных пользователей, которые пытались выборочно импортировать макросы.
Смотрите также: