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

rust学习-宏的定义与使用

rust学习-宏的定义与使用

  • 声明宏(macro_rules! 宏)
  • 使用方式
    • 1. 简单的宏
    • 2. 带参数的宏
    • 3. 多个模式的宏
  • 过程宏
    • 1. 定义过程宏
      • 1.1 属性宏
      • 1.2 函数宏
      • 1.3 派生宏
    • 2. 使用过程宏
      • 2.1 属性宏
      • 2.2 函数宏
      • 2.3 派生宏

在 Rust 中,宏(macro)是一种在编译期间生成代码的机制,宏可以以更加灵活和高效的方式编写代码,Rust中有两种主要的宏:声明宏(macro_rules! 宏)和过程宏(procedural macros)

声明宏(macro_rules! 宏)

声明宏是使用 macro_rules! 关键字定义:

macro_rules! 宏名 {($($pattern:pat) => $body:expr);($($pattern:pat) => $body:expr);// 更多模式...
}

使用方式

1. 简单的宏

示例一个用于打印消息的宏:

macro_rules! say_hello {() => {println!("Hello, world!");};
}fn main() {say_hello!();
}

2. 带参数的宏

定义一个带参数的宏,用于打印带参数的消息:

macro_rules! say_hello_to {($name:expr) => {println!("Hello, {}!", $name);};
}fn main() {say_hello_to!("XiaoMing");
}

3. 多个模式的宏

定义一个宏,支持多种模式:

macro_rules! math {($x:expr, +, $y:expr) => {$x + $y};($x:expr, -, $y:expr) => {$x - $y};
}fn main() {let result1 = math!(10, +, 5);let result2 = math!(10, -, 5);println!("10 + 5 = {}", result1); // 输出: 10 + 5 = 15println!("10 - 5 = {}", result2); // 输出: 10 - 5 = 5
}

过程宏

1. 定义过程宏

过程宏需要一个特殊的 crate 类型,并且需要使用 proc_macro 库,常见的过程宏有:属性宏(attribute-like macros)、函数宏(function-like macros)和派生宏(derive macros)

1.1 属性宏

属性宏用于在代码上添加属性,通常用于生成额外的代码或修改现有的代码

use proc_macro;
use proc_macro2::TokenStream;
use quote::quote;
use syn;#[proc_macro_attribute]
pub fn my_attribute(_attr: TokenStream, item: TokenStream) -> TokenStream {let ast = syn::parse_macro_input!(item as syn::ItemFn);let ident = &ast.sig.ident;let expanded = quote! {fn #ident() {println!("Before function call");#astprintln!("After function call");}};expanded.into()
}

1.2 函数宏

函数宏类似于传统的宏,但可以在编译时生成更复杂的代码

extern crate proc_macro;use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};#[proc_macro]
pub fn my_function(input: TokenStream) -> TokenStream {let input = parse_macro_input!(input as ItemFn);let name = &input.sig.ident;let expanded = quote! {fn #name() {println!("This is a generated function");}};expanded.into()
}

1.3 派生宏

派生宏用于为结构体或枚举生成派生的实现

extern crate proc_macro;use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};#[proc_macro_derive(MyTrait)]
pub fn my_trait_derive(input: TokenStream) -> TokenStream {let input = parse_macro_input!(input as DeriveInput);let name = &input.ident;let expanded = quote! {impl MyTrait for #name {fn my_method(&self) {println!("This is a derived method for {}", stringify!(#name));}}};expanded.into()
}

2. 使用过程宏

使用过程宏需要在 Cargo.toml 中声明依赖,并在代码中使用宏

2.1 属性宏

#[my_attribute]
fn my_function() {println!("Inside my function");
}fn main() {my_function();
}

2.2 函数宏

my_function! {fn my_generated_function() {println!("Inside generated function");}
}fn main() {my_generated_function();
}

2.3 派生宏

#[derive(MyTrait)]
struct MyStruct;trait MyTrait {fn my_method(&self);
}fn main() {let my_struct = MyStruct;my_struct.my_method();
}

相关文章:

rust学习-宏的定义与使用

rust学习-宏的定义与使用 声明宏(macro_rules! 宏)使用方式1. 简单的宏2. 带参数的宏3. 多个模式的宏 过程宏1. 定义过程宏1.1 属性宏1.2 函数宏1.3 派生宏 2. 使用过程宏2.1 属性宏2.2 函数宏2.3 派生宏 在 Rust 中,宏(macro&…...

【学习总结|DAY032】后端Web实战:登录认证

在 Web 后端开发中,登录认证是保障系统安全和用户数据隐私的关键环节。本文将结合实际开发案例,深入探讨登录功能与登录校验的实现思路和技术细节,希望能帮助读者更好地掌握这一重要知识点。 一、登录功能实现 1.1 思路分析 登录功能的核心…...

leetcode 123. 买卖股票的最佳时机 III

题目:123. 买卖股票的最佳时机 III - 力扣(LeetCode) O(N)的算法: f[i] max(max(0, prices[i] - min(prices[0], prices[1], ... , prices[i - 1)), f[i - 1]); g[i] max(max(0, max(prices[i 1], prices[i 2], ... , pric…...

Apache Tika 详解

Apache Tika是一个开源的、跨平台的库,专门用于检测、提取和解析多种文件格式的元数据。以下是对Apache Tika的详细解析: 一、概述 Apache Tika旨在为各种类型的数据提取提供一个单一的API,它支持多种文件格式,包括文档、图片、…...

ChatGPT被曝存在爬虫漏洞,OpenAI未公开承认

OpenAI的ChatGPT爬虫似乎能够对任意网站发起分布式拒绝服务(DDoS)攻击,而OpenAI尚未承认这一漏洞。 本月,德国安全研究员Benjamin Flesch通过微软的GitHub分享了一篇文章,解释了如何通过向ChatGPT API发送单个HTTP请求…...

Qt——界面优化

在Qt中进行界面优化,可以从以下几个方面入手: 1.使用QWidget:setVisible来控制Widget的 显示和隐藏,而不是删除和重建。 2.使用QPainter直 接绘制组件,避免使用复杂的布局。 3.使用QSS进行样式设置, 减少图片资源的使用。 4.使…...

python学opencv|读取图像(四十一 )使用cv2.add()函数实现各个像素点BGR叠加

【1】引言 前序已经学习了直接在画布上使用掩模,会获得彩色图像的多种叠加效果,相关文章链接为: python学opencv|读取图像(四十)掩模:三通道图像的局部覆盖-CSDN博客 这时候如果更进一步,直接…...

Spring MVC和Spring WebFlux的区别

目录 一、编程模型 二、IO处理方式 三、数据流处理 四、适用场景 五、生态系统 在当今的Web开发领域,Spring框架无疑占据着重要的地位。其中,Spring MVC和Spring WebFlux作为Spring框架中用于构建Web应用程序的两个重要模块,各自具有独特…...

Linux探秘坊-------4.进度条小程序

1.缓冲区 #include <stdio.h> int main() {printf("hello bite!");sleep(2);return 0; }执行此代码后&#xff0c;会 先停顿两秒&#xff0c;再打印出hello bite&#xff0c;但是明明打印在sleep前面&#xff0c;为什么会后打印呢&#xff1f; 因为&#xff…...

Llama 3:开源大模型的里程碑式突破

标题&#xff1a;Llama 3&#xff1a;开源大模型的里程碑式突破 文章信息摘要&#xff1a; Meta通过Llama 3展现了开源LLM的重大突破&#xff1a;采用超大规模训练数据和多阶段训练方法&#xff08;SFT、rejection sampling、PPO和DPO&#xff09;&#xff0c;突破了传统的Chi…...

计算机网络 (56)交互式音频/视频

一、定义与特点 定义&#xff1a;交互式音频/视频是指用户使用互联网和其他人进行实时交互式通信的技术&#xff0c;包括语音、视频图像等多媒体实时通信。 特点&#xff1a; 实时性&#xff1a;音频和视频数据是实时传输和播放的&#xff0c;用户之间可以进行即时的交流。交互…...

STM32 GPIO工作模式

GPIO工作模式 1. GPIO简介2. GPIO工作模式2.1 输入浮空2.2 输入上拉2.3 输入下拉2.4 模拟2.5 开漏输出2.6 推挽输出2.7 开漏式复用功能2.8 推挽式复用功能 1. GPIO简介 GPIO 是通用输入输出端口的简称&#xff0c;简单来说就是 STM32 可控制的引脚&#xff0c;STM32 芯片的 GPI…...

自动化实现的思路变化

阶段一&#xff1a; 1、成功调用。第一步&#xff0c;一般是用现用的工具&#xff0c;或者脚本成功调用接口 2、解决关联接口的参数传递。有的接口直接&#xff0c;存在参数的传递&#xff0c;一般的思路&#xff0c;就是将这个参数设置为变量。 3、简化代码。总会有些东西是重…...

MongoDB的索引与聚合

一、实验目的 1. 理解索引的概念及其在MongoDB中的重要性和作用。 2. 学习如何选择适合建立索引的字段。 3. 掌握如何创建、删除索引以及如何强制使用索引。 4. 熟悉MongoDB的聚合框架和MapReduce工具&#xff0c;以及简单聚合命令的使用。 二、实验环境准备 1. JAV…...

Java菜鸟养成计划(java基础)--java运算符

java中的运算符 1、java中的运算符1.1 、 、-、 * 、/ 、 %1.2 、、-、 *、/、%1.3 、、--【自增\自减运算符】1.4、>、 <、 > 、< 、 、! 、! 1.5、&&、||、|、&1.6、&、|、~、^1.7、>> 、 <<、>>>位运算1.8、?:三目运算符…...

除了基本的事件绑定,鸿蒙的ArkUI

鸿蒙操作系统&#xff08;HarmonyOS&#xff09;是由华为技术有限公司开发的分布式操作系统&#xff0c;旨在为多种智能设备提供一个统一的操作平台。它不仅适用于智能手机&#xff0c;还适用于平板电脑、智能手表、智能电视等物联网设备。为了使开发者能够更加便捷地创建跨设备…...

0164__【GNU】gcc -O编译选项 -Og -O0 -O1 -O2 -O3 -Os

【GNU】gcc -O编译选项 -Og -O0 -O1 -O2 -O3 -Os_gcc -o0-CSDN博客...

vue3组件传值具体使用

问&#xff1a; left.vue文件调用接口获取了后端返回的urlLink字段&#xff0c;我该怎么传递给总的父组件index.vue中&#xff0c;我需要点击父组件的一个按钮来触发跳转&#xff1f; 回答&#xff1a; 在 Vue 3 中使用 TypeScript 和 setup 语法糖时&#xff0c;可以通过 e…...

Web 音视频(二)在浏览器中解析视频

前言 浏览器中已经能直接播放视频&#xff0c;为什么还需要手动写代码解析&#xff1f; 因为&#xff0c;某些场景需要对视频进行更细致的处理&#xff0c;比如截取关键帧、提取视频中的文字、人物打码、极低延时播放视频等等。 总之&#xff0c;除了最单纯的视频播放外&…...

江天科技主要产品销售单价下滑,应收账款、存货周转率大幅下降

《港湾商业观察》廖紫雯 日前&#xff0c;苏州江天包装科技股份有限公司&#xff08;以下简称&#xff1a;江天科技&#xff09;冲击北交所&#xff0c;保荐机构为国投证券。 江天科技主要从事标签印刷产品的研发、生产与销售&#xff0c;公司主要产品包括薄膜类和纸张类的不…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

boost::filesystem::path文件路径使用详解和示例

boost::filesystem::path 是 Boost 库中用于跨平台操作文件路径的类&#xff0c;封装了路径的拼接、分割、提取、判断等常用功能。下面是对它的使用详解&#xff0c;包括常用接口与完整示例。 1. 引入头文件与命名空间 #include <boost/filesystem.hpp> namespace fs b…...

拟合问题处理

在机器学习中&#xff0c;核心任务通常围绕模型训练和性能提升展开&#xff0c;但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正&#xff1a; 一、机器学习的核心任务框架 机…...

[特殊字符] Spring Boot底层原理深度解析与高级面试题精析

一、Spring Boot底层原理详解 Spring Boot的核心设计哲学是约定优于配置和自动装配&#xff0c;通过简化传统Spring应用的初始化和配置流程&#xff0c;显著提升开发效率。其底层原理可拆解为以下核心机制&#xff1a; 自动装配&#xff08;Auto-Configuration&#xff09; 核…...

Linux实现线程同步的方式有哪些?

什么是线程同步&#xff1f; 想象一下超市收银台&#xff1a;如果所有顾客&#xff08;线程&#xff09;同时挤向同一个收银台&#xff08;共享资源&#xff09;&#xff0c;场面会一片混乱。线程同步就是给顾客们发"排队号码牌"&#xff0c;确保&#xff1a; 有序访…...

JS的传统写法 vs 简写形式

一、条件判断与逻辑操作 三元运算符简化条件判断 // 传统写法 let result; if (someCondition) {result yes; } else {result no; }// 简写方式 const result someCondition ? yes : no;短路求值 // 传统写法 if (condition) {doSomething(); }// 简写方式 condition &…...