学习 Rust 声明宏
Rust 的声明宏是一种类似于 C 语言中的宏, 用于声明代码片段, 通过宏展开生成代码.
语法
声明宏使用 macro_rules! 关键字声明, 语法如下:
macro_rules! macro_name {
(pattern1) => {
// code1
};
(pattern2) => {
// code2
};
}元变量
item: 程序项block: 块表达式stmt: 语句pat_param: 模式pat: 模式expr: 表达式ty: 类型ident: 标识符path: 路径tt: token树meta: 属性中的内容lifetime: 生命周期tokenvis: 可能为空的可见性修饰符literal: 字面量
- 从 2021 edition 开始,
pat可以匹配顶层或模式- 在 2021 edition 之前,
pat和pat_param相同
重复
和正则类似, 可以使用 *, +, ? 来表示重复次数:
*: 0 次或多次+: 1 次或多次?: 0 次或 1 次
使用
macro_use
装饰模块, 使得模块中的宏可以在其他模块中使用
macro_export
装饰宏, 使宏在 crate:: 域中声明, 即可以使用 crate::my_macro! 的形式调用
示例
多规则
macro_rules! add {
($a: expr, $b: expr) => {
$a + $b
};
($a: expr, $b: expr, $c: expr) => {
$a + $b + $c
};
($a: expr, $b: expr, $c: expr, $d: expr) => {
$a + $b + $c + $d
};
}
fn main() {
let sum1 = add!(1, 2);
let sum2 = add!(1, 2, 3);
let sum3 = add!(1, 2, 3, 4);
println!("sum1: {}, sum2: {}, sum3: {}", sum1, sum2, sum3);
// sum1: 3, sum2: 6, sum3: 10
}重复 & 嵌套调用
macro_rules! add {
($a: expr) => {
$a
};
($a: expr, $($b: expr),+) => {
$a + add!($($b),+)
};
}
fn main() {
let sum1 = add!(1, 2);
let sum2 = add!(1, 2, 3);
let sum3 = add!(1, 2, 3, 4);
let sum4 = add!(1, 2, 3, 4, 5);
let sum5 = add!(1, 2, 3, 4, 5, 6);
println!(
"sum1: {}, sum2: {}, sum3: {}, sum4: {}, sum5: {}",
sum1, sum2, sum3, sum4, sum5
);
// sum1: 3, sum2: 6, sum3: 10, sum4: 15, sum5: 21
}综合使用
macro_rules! my_errors {
($( $variant: ident => $reason: expr ),* $(,)?) => {
#[derive(Debug)]
pub enum MyError {
$($variant { reason: &'static str },)*
}
impl MyError {
$(
#[allow(non_upper_case_globals)]
pub const $variant: MyError = MyError::$variant { reason: $reason };
)*
pub fn reason(&self) -> &str {
match self {
$(MyError::$variant { reason } => reason),*
}
}
}
}
}
my_errors!(
NotFound => "not found",
BadRequest => "bad request",
Unauthorized => "unauthorized",
);
fn main() {
let error1 = MyError::NotFound;
let error2 = MyError::BadRequest;
let error3 = MyError::Unauthorized;
println!("{}", error1.reason());
println!("{}", error2.reason());
println!("{}", error3.reason());
// not found
// bad request
// unauthorized
}复杂案例
标记树撕咬机 (tt muncher)