Syntax @符号在声明性宏中是什么意思?

Syntax @符号在声明性宏中是什么意思?,syntax,rust,rust-macros,rust-decl-macros,Syntax,Rust,Rust Macros,Rust Decl Macros,我见过宏中使用的@符号,但在铁锈书或任何官方文档或博客帖子中都找不到它。例如,在中,它是这样使用的: macro_rules! instructions { (enum $ename:ident { $($vname:ident ( $($vty: ty),* )),* }) => { enum $ename { $($vname ( $($vty),* )),* } impl $en

我见过宏中使用的
@
符号,但在铁锈书或任何官方文档或博客帖子中都找不到它。例如,在中,它是这样使用的:

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());
}
从用法来看,它似乎用于声明另一个宏,该宏是主宏的本地宏


这个符号是什么意思?为什么要使用它而不仅仅是创建另一个顶级宏?

在宏的模式匹配部分,符号可以表示作者希望它们表示的任何意思。前导符号
@
通常用于表示宏的“实现细节”——外部用户不希望使用的宏的一部分

在本例中,我使用它对元组参数进行模式匹配,以获得元组参数的计数

在宏之外,
@
符号用于匹配图案,同时也为整个图案指定名称:

match age {
    x @ 0 => println!("0: {}", x),
    y @ 1 => println!("1: {}", y),
    z => println!("{}", z),
}
稍微扩展一下,同样的逻辑也可以应用于宏中的使用-我们是模式匹配元组,但也为特定模式附加了一个名称。我想我甚至见过人们使用更为相似的东西:
(count@…
。然而,我指出:

使用
@
的原因是,从Rust 1.2开始,
@
标记不用于前缀位置;因此,它不会与任何内容冲突。可以根据需要使用其他符号或唯一前缀,但
@
的使用已开始普及,因此使用它可以帮助读者理解您的代码


而不仅仅是创建另一个顶级宏

创建另一个宏可能是更好的做法,但只适用于现代的Rust。在最近对Rust所做的更改使您可以直接导入宏之前,对于尝试选择性导入宏的最终用户来说,拥有多个宏可能很棘手

另见:


啊……太明显了!我不知怎么地认为这是一种特殊的语法,无法动摇这个想法。等等,如果x==0,那么
x@0
相当于
x
?引入另一个符号有什么意义?@OptimisticPeach这当然不是一个常见的用例,但有些情况下你需要模式匹配和绑定一个名称。你可以match Guard的参数也是一样的,如果在match arm中使用表达式,那么很多时候它们可以是
$($ename::$vname(..)=>指令!(@count($($vty),*),*),*
–我没有得到这部分。
$vname(..)中的参数数量是多少
等于右侧的
$vty
数量。