Что означает символ @ в декларативном макросе? - PullRequest
0 голосов
/ 28 января 2019

Я видел символ @, используемый в макросах, но я не могу найти упоминания о нем в 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 Ответ

0 голосов
/ 28 января 2019

В части макроса, соответствующей шаблону, символы могут означать то, что автор хочет, чтобы они значили.Ведущий символ @ часто используется для обозначения «детали реализации» макроса - части макроса, которую внешний пользователь не должен использовать.

В этом примере я использовал его для создания шаблона- сопоставить параметры кортежа, чтобы получить счетчик параметров кортежа.

Вне макросов символ @ используется для сопоставления с шаблоном, а также для присвоения имени всему шаблону:

match age {
    x @ 0 => println!("0: {}", x),
    y @ 1 => println!("1: {}", y),
    z => println!("{}", z),
}

С некоторой растяжкой эту же логику можно применить к использованию в макросе - мы сопоставляем шаблон с кортежем, но также прикрепляем имя к этому конкретному шаблону.Я думаю Я даже видел, как люди используют что-то еще более параллельное: (count @ ....Тем не менее, Маленькая книга макросов ржавчины указывает:

Причина использования @ заключается в том, что, начиная с Rust 1.2, @ токен не используется в позиции префикса;как таковой, он не может конфликтовать ни с чем.Другие символы или уникальные префиксы могут использоваться по желанию, но использование @ стало широко распространяться, поэтому его использование может помочь читателям понять ваш код.


чем просто создание другого макроса верхнего уровня

Создание другого макроса, вероятно, является лучшей практикой, но только в современном Rust.До недавних изменений в Rust, которые позволили вам импортировать макросы напрямую, иметь несколько макросов было сложно для конечных пользователей, которые пытались выборочно импортировать макросы.

См. Также:

...