@ 符号在 Rust 声明宏中意味着什么?
What does an @ symbol mean in a Rust declarative macro?
我见过宏中使用的 @
符号,但我在 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());
}
从用法来看,它似乎用于声明另一个宏,该宏是主宏的本地宏。
这个符号是什么意思,为什么要使用它而不是仅仅创建另一个顶级宏?
在宏的模式匹配部分,符号可以表示作者希望它们表示的任何含义。前导符号 @
通常用于表示宏的 "implementation detail" — 外部用户不应使用的宏的一部分。
在此示例中,我使用它对元组参数进行模式匹配以获得元组参数的计数。
在宏之外,@
符号用于匹配模式,同时还为整个模式分配名称:
match age {
x @ 0 => println!("0: {}", x),
y @ 1 => println!("1: {}", y),
z => println!("{}", z),
}
稍微延伸一下,同样的逻辑可以应用于宏中的使用——我们正在对元组进行模式匹配,但也为该特定模式附加了一个名称。我 认为 我什至看到人们使用更平行的东西:(count @ ...
。但是,The Little Book of Rust Macros指出:
The reason for using @
is that, as of Rust 1.2, the @
token is not used in prefix position; as such, it cannot conflict with anything. Other symbols or unique prefixes may be used as desired, but use of @
has started to become widespread, so using it may aid readers in understanding your code.
rather than just creating another top-level macro
创建另一个宏可能是更好的做法,但仅限于现代 Rust。在最近对 Rust 的更改使您可以直接导入宏之前,拥有多个宏对于尝试有选择地导入宏的最终用户来说可能会很棘手。
另请参阅:
我见过宏中使用的 @
符号,但我在 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());
}
从用法来看,它似乎用于声明另一个宏,该宏是主宏的本地宏。
这个符号是什么意思,为什么要使用它而不是仅仅创建另一个顶级宏?
在宏的模式匹配部分,符号可以表示作者希望它们表示的任何含义。前导符号 @
通常用于表示宏的 "implementation detail" — 外部用户不应使用的宏的一部分。
在此示例中,我使用它对元组参数进行模式匹配以获得元组参数的计数。
在宏之外,@
符号用于匹配模式,同时还为整个模式分配名称:
match age {
x @ 0 => println!("0: {}", x),
y @ 1 => println!("1: {}", y),
z => println!("{}", z),
}
稍微延伸一下,同样的逻辑可以应用于宏中的使用——我们正在对元组进行模式匹配,但也为该特定模式附加了一个名称。我 认为 我什至看到人们使用更平行的东西:(count @ ...
。但是,The Little Book of Rust Macros指出:
The reason for using
@
is that, as of Rust 1.2, the@
token is not used in prefix position; as such, it cannot conflict with anything. Other symbols or unique prefixes may be used as desired, but use of@
has started to become widespread, so using it may aid readers in understanding your code.
rather than just creating another top-level macro
创建另一个宏可能是更好的做法,但仅限于现代 Rust。在最近对 Rust 的更改使您可以直接导入宏之前,拥有多个宏对于尝试有选择地导入宏的最终用户来说可能会很棘手。
另请参阅: