声明宏 macro_rules!
学习目标
- 理解声明宏的作用
- 掌握模式匹配语法
- 编写常用宏
核心概念
基本语法
macro_rules! say_hello {
() => {
println!("Hello!");
};
}
fn main() {
say_hello!();
}
带参数
macro_rules! greet {
($name:expr) => {
println!("Hello, {}!", $name);
};
($name:expr, $greeting:expr) => {
println!("{}, {}!", $greeting, $name);
};
}
fn main() {
greet!("Rust");
greet!("Rust", "Hi");
}
重复模式
macro_rules! vec_of_strings {
($($s:expr),* $(,)?) => {
vec![$($s.to_string()),*]
};
}
fn main() {
let v = vec_of_strings!["hello", "world", "rust"];
println!("{:?}", v);
}
常用宏示例
macro_rules! hashmap {
($($key:expr => $value:expr),* $(,)?) => {{
let mut map = std::collections::HashMap::new();
$(map.insert($key, $value);)*
map
}};
}
fn main() {
let scores = hashmap! {
"Alice" => 95,
"Bob" => 87,
};
println!("{:?}", scores);
}
捕获类型
macro_rules! debug_print {
($var:ident) => {
println!("{} = {:?}", stringify!($var), $var);
};
($expr:expr) => {
println!("{} = {:?}", stringify!($expr), $expr);
};
}
fn main() {
let x = 42;
debug_print!(x);
debug_print!(2 + 3);
}
实践练习
练习 1:计时宏
macro_rules! time_it {
($label:expr, $block:block) => {{
let start = std::time::Instant::now();
let result = $block;
let elapsed = start.elapsed();
println!("{}: {:?}", $label, elapsed);
result
}};
}
fn main() {
let sum = time_it!("求和", {
(1..=1_000_000).sum::<i64>()
});
println!("结果: {}", sum);
}
练习 2:自动实现 Display
macro_rules! impl_display {
($type:ty, $format:expr) => {
impl std::fmt::Display for $type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, $format, self)
}
}
};
}
struct Point {
x: f64,
y: f64,
}
impl_display!(Point, "({}, {})");
fn main() {
let p = Point { x: 1.0, y: 2.0 };
println!("{}", p);
}
小结
| 语法 | 说明 |
|---|
$name:expr | 捕获表达式 |
$name:ident | 捕获标识符 |
$name:ty | 捕获类型 |
$($x:expr),* | 重复(逗号分隔) |
$($x:expr),+ | 重复(至少一个) |
$(...)? | 可选 |
stringify! | 转字符串 |