Rust 语言宏(Macro)简介 😊
概述
宏是 Rust 语言中的元编程机制,可以在编译期间扩展代码。它们允许我们在编写代码时使用元编程技术,例如重复代码和代码自动生成。
Rust 中有二种宏:函数宏
和 属性宏
。
函数宏
函数宏使用 macro_rules!
关键字定义,其可以像函数一样接收输入,并产生输出。通常情况下,它们用于生成代码,例如根据输入数据动态生成代码。函数宏可以是纯函数,也可以与外部环境交互,这种宏类似于 C/C++ 中的宏。
下面是一个函数宏的简单示例:
1#[macro_export]
2macro_rules! multiply {
3 ($x:expr, $y:expr) => {
4 $x * $y
5 };
6}
7
8fn main() {
9 let result = multiply!(3, 4);
10 println!("{}", result); // 输出 12
11}
这个宏将两个表达式作为参数,并返回它们的乘积。在主函数中,我们调用 multiply!
宏来计算 3 * 4
并将结果打印到控制台。
属性宏
属性宏是基于 proc_macro
crate 实现的。其可以被用于任何项,例如结构体、枚举和函数,可以读取和操作属性,也可以将属性转换为代码。简单来讲,其接收一个 Rust 代码块作为输入,并将其转换为新的代码块,类似于 Python 中装饰器的方式修改代码。
下面是一个属性宏的完整示例:
1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput};
4
5#[proc_macro_attribute]
6pub fn my_attr(_: TokenStream, input: TokenStream) -> TokenStream {
7 // 将 TokenStream 转化为 AST
8 let input = parse_macro_input!(input as DeriveInput);
9
10 // 从 AST 中获取结构体名字
11 let name = input.ident;
12
13 // 构造输出的 TokenStream
14 let expanded = quote! {
15 impl #name {
16 pub fn my_method(&self) {
17 println!("This is a method added by my_attr!");
18 }
19 }
20 };
21
22 // 将 TokenStream 转化为输出结果
23 TokenStream::from(expanded)
24}
这个属性宏会为被标记的结构体添加一个方法 my_method
。使用方法如下:
1#[my_attr]
2struct MyStruct;
3
4fn main() {
5 let my_struct = MyStruct;
6 my_struct.my_method();
7}
输出结果为:
1This is a method added by my_attr!
番外
自定义派生(derive
)宏是一种属性宏,用于自动实现某些 trait
,例如 Clone
和 Debug
。当使用派生宏时,编译器会自动为您的结构体或枚举类型实现相关的 trait
,无需手动编写代码。
终末
宏是 Rust 语言中一个强大的元编程工具,可以大大简化代码编写和重复的工作,并帮助开发者编写更加灵活和易于维护的代码。