当前位置: 首页 > news >正文

Rust进阶-part6-宏

Rust进阶[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 中强大的代码生成工具,声明宏通过模式匹配生成代码,过程宏则提供了更灵活的代码生成方式,包括派生宏、属性宏和函数宏。

应用场景

  1. 减少重复代码: 通过宏生成重复的代码,提高代码的可维护性。
  2. 编译期计算:在编译器进行计算并生成代码,提高运行时性能。
  3. 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;)*  // 对每个捕获的表达式,生成一次累加语句
http://www.lryc.cn/news/615800.html

相关文章:

  • [激光原理与应用-224]:机械 - 机械设计与加工 - 常见的术语以及含义
  • 每日算法刷题Day60:8.10:leetcode 队列5道题,用时2h
  • 机器学习-增加样本、精确率与召回率
  • Modbus RTU转Profinet网关接在线循环Na离子实现PLC读取温度值
  • C# 中常用集合以及使用场景
  • 本地WSL部署接入 whisper + ollama qwen3:14b 总结字幕增加利用 Whisper 分段信息,全新 Prompt功能
  • Framework开发之Zygote进程2(基于开源的AOSP15)--init.rc在start zygote之后的事情(详细完整版逐行代码走读)
  • 《解锁 C++ 基础密码:输入输出、缺省参数,函数重载与引用的精髓》
  • 【Linux | 网络】数据链路层
  • 九、Linux Shell脚本:运算符与表达式
  • 开启单片机
  • 服务器硬件电路设计之 I2C 问答(三):I2C 总线上可以接多少个设备?如何保证数据的准确性?
  • 笔试——Day34
  • 亚麻云之全球加速器——CloudFront(CDN)服务入门
  • 【Docker实战】Spring Boot应用容器化
  • ShadowKV 机制深度解析:高吞吐长上下文 LLM 推理的 KV 缓存“影子”方案
  • Python爬虫-爬取政务网站的文档正文内容和附件数据
  • 【后端】Java 8 特性 `User::getId` 语法(方法引用)介绍
  • 【东枫科技】NTN-IOT 卫星互联网原型系统,高达1.6G大带宽
  • MPLS特性之PHP(Penultimate Hop Popping)
  • Android快速视频解码抽帧FFmpegMediaMetadataRetriever,Kotlin(2)
  • 【软考中级网络工程师】知识点之 DCC 深度剖析
  • 【21】OpenCV C++实战篇——OpenCV C++案例实战二十七《角度测量》
  • Perplexity 为特朗普 Truth Social 提供技术支持
  • 如何培养自己工程化的能力(python项目)
  • Pytorch深度学习框架实战教程12:Pytorch混合精度推理,性能加速147%的技术实现
  • 若依前后端分离版学习笔记(八)——事务简介与使用
  • Apache Pulsar性能与可用性优化实践指南
  • NLP---IF-IDF案例分析
  • C++高频知识点(十九)