为什么编译器不自动在声明性宏中添加双括号?
Why does the compiler not adds double brackets in a declarative macro automatically?
在声明性宏中创建标识符时,必须在宏中放置额外的括号(双括号)。我想知道为什么编译器不只是(总是)添加额外的括号。
示例 1:此代码将无法编译,因为在强制使用双括号的地方只使用了单括号:
macro_rules! some_macro {
() => {
let mut x = 1;
x += 1;
x
};
}
fn main() {
let y = some_macro!();
}
添加双括号解决了编译错误。
示例 2:无论使用单括号还是双括号,这段代码都能编译通过:
macro_rules! some_macro {
() => {{
1
}};
}
fn main() {
let y = some_macro!();
}
是否存在双括号宏会破坏单括号宏的情况?如果不是,为什么编译器不总是添加双括号?
有时双括号会失败。由于内部大括号创建了一个范围,如果你想声明任何标识符,它们将不会被“导出”:
// compiles with single braces but not double braces
macro_rules! set_ident_to_1 {
($var: ident) => {
let $var = 1;
}
}
fn main() {
set_ident_to_1!(foo);
println!("{}", foo);
}
也可能存在不允许直接使用大括号的情况,例如顶级定义。以这个创建重复 Deref
实现的宏为例:
struct Foo {
x: i32
}
struct Bar {
y: u32
}
// compiles with single braces but not double braces
macro_rules! create_repetitive_impl {
($prop: ident, $typ: ty, $target: ty) => {
impl std::ops::Deref for $typ {
type Target = $target;
fn deref(&self) -> &Self::Target {
&self.$prop
}
}
}
}
create_repetitive_impl!(x, Foo, i32);
create_repetitive_impl!(y, Bar, u32);
fn main() {
println!("{:?}", Foo {x: 5}.checked_mul(6))
}
在声明性宏中创建标识符时,必须在宏中放置额外的括号(双括号)。我想知道为什么编译器不只是(总是)添加额外的括号。
示例 1:此代码将无法编译,因为在强制使用双括号的地方只使用了单括号:
macro_rules! some_macro {
() => {
let mut x = 1;
x += 1;
x
};
}
fn main() {
let y = some_macro!();
}
添加双括号解决了编译错误。
示例 2:无论使用单括号还是双括号,这段代码都能编译通过:
macro_rules! some_macro {
() => {{
1
}};
}
fn main() {
let y = some_macro!();
}
是否存在双括号宏会破坏单括号宏的情况?如果不是,为什么编译器不总是添加双括号?
有时双括号会失败。由于内部大括号创建了一个范围,如果你想声明任何标识符,它们将不会被“导出”:
// compiles with single braces but not double braces
macro_rules! set_ident_to_1 {
($var: ident) => {
let $var = 1;
}
}
fn main() {
set_ident_to_1!(foo);
println!("{}", foo);
}
也可能存在不允许直接使用大括号的情况,例如顶级定义。以这个创建重复 Deref
实现的宏为例:
struct Foo {
x: i32
}
struct Bar {
y: u32
}
// compiles with single braces but not double braces
macro_rules! create_repetitive_impl {
($prop: ident, $typ: ty, $target: ty) => {
impl std::ops::Deref for $typ {
type Target = $target;
fn deref(&self) -> &Self::Target {
&self.$prop
}
}
}
}
create_repetitive_impl!(x, Foo, i32);
create_repetitive_impl!(y, Bar, u32);
fn main() {
println!("{:?}", Foo {x: 5}.checked_mul(6))
}