繁体   English   中英

Rust 声明性宏中的 @ 符号是什么意思?

[英]What does an @ symbol mean in a Rust declarative macro?

我见过宏中使用的@符号,但在 Rust Book 或任何官方文档或博客文章中找不到提及它。 例如,在这个 Stack Overflow 答案中,它是这样使用的:

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 @ ... 。然而,The Little Book of Rust Macros指出:

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


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

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

也可以看看:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM