Rust进阶[part6]_宏

AI-摘要
sonia33 GPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
Rust进阶[part6]_宏
SoniaChenRust进阶[part6]_宏
macro 概述
宏是 Rust 中强大的代码生成工具,与函数不同,它在编译期展开并生成具体代码,能处理可变参数、实现动态逻辑,语法上以 !
结尾(如 println!
vec!
panic!
)。
常用宏简化了重复操作:println!
处理格式化输出,vec!
快速创建向量,cfg!
做条件编译判断。宏支持模式匹配和代码生成,比函数更灵活,但也因编译期处理,调试和学习门槛稍高。按功能可分为声明宏(基于模式匹配)和过程宏(更复杂的代码生成),是 Rust 元编程的核心能力。
一些之前常用的宏,例如 println!
、vec!
等,它们简化了代码编写。
声明宏
声明宏允许你通过模式匹配来生成代码。例如,下面是一个简单的加法声明宏:
macro_rules! add {
($a:expr, $b:expr) => {
$a + $b
};
}
fn main() {
let result = add!(1, 2);
println!("Result: {}", result);
}
格式
macro_rules! 宏名称 {
(模式1) => { 代码1 };
(模式2) => { 代码2 };
// ...
}
- 模式:匹配调用宏时的输入参数。
- 元变量:用
$
开头,捕获输入的片段(如表达式、标识符等)。 - 重复符号:
*
(零或多次)、+
(至少一次),类似正则表达式。
过程宏
派生宏
派生宏可以为结构体、枚举等类型自动生成代码。例如,使用 #[derive(Debug)]
可以自动为结构体添加调试输出的能力:
#[derive(Debug)]
struct Person {
name: String,
age: u8,
}
fn main() {
let person = Person {
name: String::from("Alice"),
age: 30,
};
println!("{:?}", person);
}
属性宏
属性宏可以为函数、结构体等添加自定义属性。例如,自定义一个日志属性宏:
#[proc_macro_attribute]
pub fn log(_attr: TokenStream, item: TokenStream) -> TokenStream {
// 这里可以实现日志记录逻辑
item
}
#[log]
fn my_function() {
println!("Function called");
}
fn main() {
my_function();
}
函数宏
函数宏类似于普通函数,但在编译时展开。例如:
#[proc_macro]
pub fn greet(_item: TokenStream) -> TokenStream {
let code = "println!(\"Hello, world!\");";
code.parse().unwrap()
}
fn main() {
greet!();
}
总结
宏是 Rust 中强大的代码生成工具,声明宏通过模式匹配生成代码,过程宏则提供了更灵活的代码生成方式,包括派生宏、属性宏和函数宏。
应用场景
- 减少重复代码: 通过宏生成重复的代码,提高代码的可维护性。
- 编译期计算:在编译器进行计算并生成代码,提高运行时性能。
- DSL(领域特定语言):使用宏定义领域特定语言,提高代码的表达力和可读性。
课后习题
实现一下宏
assert_eq!(repeat!("x", 3), "xxx");
assert_eq!(sum!(1, 2, 3, 4, 5), 15);
assert_eq!(max_value!(1, 8, 9), 9);
代码:
#[macro_export]
macro_rules! say_hello {
() => {
println!("hello!");
};
($name:expr) => {
println!("hello {}!", $name);
};
}
#[macro_export]
macro_rules! repeat {
() => {
println!("repeat!");
};
($s:expr, $n:expr) => {
std::string::String::from($s).repeat($n)
};
}
#[macro_export]
macro_rules! sum {
() => {
println!("sum!");
};
($($x:expr),*) => {
{
let mut total = 0;
$(total += $x;)*
total
}
};
}
#[macro_export]
macro_rules! max_value {
() => {
println!("max_value!");
};
($x:expr, $y:expr, $z:expr) => {
if $x > $y {
if $x > $z { $x } else { $z }
} else {
if $y > $z { $y } else { $z }
}
};
}
一些符号拆解:
$()
:分组捕获元变量。\*
/+
:重复匹配输入片段。$(...)\*
:在展开时代入重复的代码逻辑。
// sum! 宏展开逻辑
$(total += $x;)* // 对每个捕获的表达式,生成一次累加语句
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果