声明式宏(`macro_rules!`)
学习编写声明式宏,以抽象重复的代码模式,并在编译时生成代码。
声明式宏(`macro_rules!`) 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 1 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 3 节课。
什么是 Rust 宏?
宏是一种编写能够生成代码的代码的方式!它们类似于函数,但操作的是语法树(即代码的结构),而不是值。
- 它们有助于抽象重复代码。
- 它们支持在 Rust 中实现领域专用语言(DSL)。
- 它们在编译时运行,在编译开始前展开为普通的 Rust 代码。
声明式宏语法
Rust 的声明式宏使用macro_rules!关键字。它们定义一组规则,用于匹配特定的 Rust 代码模式。
您可以把它理解为针对代码片段的模式匹配。当编译器看到宏调用时,它会尝试将输入与您定义的某条规则匹配。
您的第一个 `macro_rules!`
让我们创建一个非常简单的宏,用于打印问候语。请注意macro_rules!关键字和() => {}语法,它定义了一个不带输入模式的规则。
请尝试运行这个示例:
macro_rules! greet {
() => {
println!("Hello from a macro!");
};
}
fn main() {
greet!(); // Call our macro!
}使用设计符捕获输入
宏可以使用“设计符”接收输入。这些设计符会告诉宏应当捕获哪种 Rust 语法。
$expr:一个表达式(例如1 + 2、"hello")$ident:一个标识符(例如变量名、函数名)$ty:一个类型(例如i32、String)$block:一个代码块(例如{ ... })- ……以及更多!
接收参数的宏
下面是一个接收表达式($e:expr)并打印其值的宏。这里的:expr就是设计符。
捕获的$e随后就可以在宏体中使用。stringify!宏会将表达式转换为其字符串表示形式。
macro_rules! debug_print {
($e:expr) => {
println!("Debug: {} = {:?}", stringify!($e), $e);
};
}
fn main() {
let x = 10;
debug_print!(x + 5);
debug_print!("Rust macros are fun");
}处理多个输入
如果您希望宏接受多个相同类型的参数,可以使用重复运算符:$()*。
$():其中的内容是要重复的模式。*:重复零次或多次。+:重复一次或多次。- 您还可以指定分隔符,例如使用
$(...),*表示以逗号分隔的项目。
带重复参数的宏
让我们创建一个接受多个表达式(以逗号分隔)的宏,并分别打印每个表达式。这对于创建类似列表的结构非常有用。
macro_rules! print_all {
( $( $x:expr ),* ) => {
$( // This $(...)* repeats the `println!` call
println!("Item: {:?}", $x);
)*
};
}
fn main() {
print_all!(1, "hello", true, 3.14);
print_all!("Just one item");
}理解宏卫生性
Rust 的宏具有“卫生性”。这意味着,在宏内部定义的变量不会意外地与宏外部的变量发生冲突,即使它们的名称相同。
编译器会在展开过程中在内部重命名相关内容,以避免非预期的副作用,从而让宏更安全、更易于预测。
如何调试宏
有时宏的展开结果可能与您的预期不同。Rust 提供了查看展开后代码的方法:
- 运行
cargo expand(需要安装cargo-expand工具) - 直接对源文件使用
rustc --pretty expanded。
这会显示宏生成的原始 Rust 代码,对于调试和理解复杂的宏行为非常有帮助!
宏模式匹配测验
请考虑以下宏定义:
macro_rules! make_tuple {
( $x:expr, $y:expr ) => {
($x, $y)
};
}以下哪一行可以成功编译并使用 make_tuple! 宏?
回顾:声明式宏
在本课中,您学习了使用 macro_rules! 的声明式宏:
- 它们在编译时生成代码,将重复的模式抽象出来。
- 它们使用模式匹配,根据语法捕获输入。
- 诸如
$expr、$ident这样的指示符用于指定预期的语法类型。 - 诸如
$()*这样的重复运算符可以处理带有灵活分隔符的多个参数。 - 宏具有卫生性,可以防止名称意外冲突。
宏是 Rust 中减少样板代码以及创建灵活、易用 API 的强大工具!
常见问题解答
「声明式宏(`macro_rules!`)」课时是免费的吗?
是的 — 「声明式宏(`macro_rules!`)」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 3 节课。
「声明式宏(`macro_rules!`)」这节课中我会学到什么?
学习编写声明式宏,以抽象重复的代码模式,并在编译时生成代码。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 3 节。
「声明式宏(`macro_rules!`)」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 声明式宏(`macro_rules!`)
- 过程宏:派生宏与函数宏
- 与不安全 Rust 交互