范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Rust学习笔记(五十九)宏

  宏macro
  宏在Rust里是指一组相关特性的集合称谓: 使用macro_rules!构建的声明宏(declarative macro) 3种过程宏 自定义#[derive]宏,用于struct或enum,可以为其指定随derive属性添加的代码 类似属性的宏,可以在任意条目上添加自定义属性 类似于函数的宏,看起来像函数调用,对其指定为参数的token进行操作
  macro_rules! 中有一些奇怪的地方。在将来,会有第二种采用 macro 关键字的声明宏,其工作方式类似但修复了这些极端情况。在此之后,macro_rules! 实际上就过时(deprecated)了。在此基础之上,同时鉴于大多数 Rust 程序员 使用 宏而非 编写 宏的事实,此处不再深入探讨 macro_rules!。请查阅在线文档或其他资源,如 "The Little Book of Rust Macros(https://danielkeep.github.io/tlborm/book/index.html)" 来更多地了解如何写宏。函数与宏的差别
  从本质上看,宏是用来编写可以生成其它代码的代码(元编程,metaprograming)。 函数在定义签名时,必须声明参数的个数和类型,而宏可以处理可变的参数。编译器会在解释代码前展开宏。宏的定义比函数复杂得多,难以阅读、理解和维护。在某个文件调用宏时,必须提前定义宏或将宏引入当前作用域。而函数可以在任何位置定义并在任何位置使用。 基于属性来生成代码的过程宏
  这种形式更像函数(某种形式的过程)一些。它会接收并操作输入的Rust代码,并生成另外一些Rust代码作为结果。
  三种过程宏: 自定义派生 属性宏 函数宏
  创建过程宏时,宏定义必须单独放在它们自己的包中,并且使用特殊的包类型。例: //src/lib.rs use proc_macro;  #[some_attribute]//some_attribute 是一个使用特定宏的占位符。 pub fn some_name(input: TokenStream) -> TokenStream {//TokenStream 类型由包含在 Rust 中的 proc_macro crate 定义并表示token序列。 这是宏的核心:宏所操作的源代码构成了输入 TokenStream,宏产生的代码是输出 TokenStream。 } 自定义derive宏(派生宏)
  需求: 创建一个hello_macro library包,定义一个拥有关联函数hello_macro的HelloMacro trait 我们定义一个能自动实现该trait的过程宏 只需要在对应的类型上标准#[derive(HelloMacro)],就能得到hello_macro函数的默认实现
  首先新建并打开文件夹macro_demo,然后新建一个Cargo.toml文件,定义工作空间,内容如下 [workspace]  members = [     "hello_macro",     "hello_macro_derive",     "pancakes", ]
  在macro_demo目录下下分别用命令行执行 > cargo new hello_macro --lib > cargo new hello_macro_derive --lib > cargo new pancakes
  其中hello_macro是定义HelloMacro trait的包,hello_macro_derive是定义派生宏的包,pancakes是使用派生宏的包。
  在hello_macro的lib.rs里定义HelloMacro trait pub trait HelloMacro {     fn hello_macro(); }
  修改hello_macro_derive的Cargo.toml如下,其中两个依赖是用来解析和生成TokenStream的。 [package] name = "hello_macro_derive" version = "0.1.0" edition = "2021"  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html  [lib] proc-macro = true  [dependencies] syn = "1.0.84" quote = "1.0.14"
  在hello_macro_derive里的lib.rs里创建派生宏如下 extern crate proc_macro;  use crate::proc_macro::TokenStream; use quote::quote; use syn;   #[proc_macro_derive(HelloMacro)] pub fn proc_macro_derive(input: TokenStream) -> TokenStream {     let ast = syn::parse(input).unwrap();     impl_hello_macro(&ast) }  fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {     let name = &ast.ident;      let gen = quote! {         impl HelloMacro for #name {             fn hello_macro() {                 println!("Hello, Macro! My name is {}", stringify!(#name));             }         }     };     gen.into() }
  其中proc_macro是编译器用来读取和操作我们 Rust 代码的 API;syn crate 将字符串中的 Rust 代码解析成为一个可以操作的数据结构;quote 则将 syn 解析的数据结构转换回 Rust 代码。 首先调用syn::parse(input).unwrap()将输入的代码解析为抽象语法树,它的部分结构如下: DeriveInput {     // --snip--      ident: Ident {         ident: "Pancakes",         span: #0 bytes(95..103)     },     data: Struct(         DataStruct {             struct_token: Struct,             fields: Unit,             semi_token: Some(                 Semi             )         }     ) }
  以上是当我们有一个自定义结构体Pancakes,并在上面标注我们定义的派生宏时解析成的。
  然后定义了一个方法impl_hello_macro,读取抽象语法树并生成我们需要的代码。&ast.ident就是被标注该宏的结构体的名字。 quote! 宏让我们可以编写希望返回的 Rust 代码。quote! 宏执行的直接结果并不是编译器所期望的并需要转换为 TokenStream。为此需要调用 into 方法,它会消费这个中间表示(intermediate representation,IR)并返回所需的 TokenStream 类型值。
  这个宏也提供了一些非常酷的模板机制;我们可以写 #name ,然后 quote! 会以名为 name 的变量值来替换它。你甚至可以做一些类似常用宏那样的重复代码的工作。 我们期望我们的过程式宏能够为通过 #name 获取到的用户注解类型生成 HelloMacro trait 的实现。该 trait 的实现有一个函数 hello_macro ,其函数体包括了我们期望提供的功能:打印 Hello, Macro! My name is 和注解的类型名。
  接着在pancakes包的Cargo.toml里添加我们创建的前两个包为依赖: [package] name = "pancakes" version = "0.1.0" edition = "2021"  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html  [dependencies] hello_macro = {path = "../hello_macro"} hello_macro_derive = {path = "../hello_macro_derive"}
  最后在其main.rs里使用自定义的派生宏: use hello_macro_derive::HelloMacro; use hello_macro::HelloMacro;  #[derive(HelloMacro)] struct Pancakes{}  fn main() {     Pancakes::hello_macro(); }
  运行cargo run,会打印Hello, Macro! My name is Pancakes。可以看出我们自定义的宏已经为结构体Pancakes自动实现了HelloMacro trait的关联函数hello_macro。 属性宏
  属性宏与自定义derive宏(派生宏)类型: 允许创建新的属性 但是不为derive属性生成代码
  属性宏更加灵活: derive宏只能用于结构体和枚举 属性宏可以用于任意条目,如函数
  例子,可以创建一个名为 route 的属性用于注解 web 应用程序框架(web application framework)的函数: #[route(GET, "/")] fn index() {}
  其宏定义的函数签名看起来像这样: #[proc_macro_attribute] pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {}
  其中attr是(GET, "/"),item对应index函数。
  类属性宏与自定义派生宏工作方式一致:创建 proc-macro crate 类型的包并实现希望生成代码的函数!函数宏
  函数宏是类似于函数调用的宏,但它比普通函数更加灵活。函数宏可以接收TokenStream作为参数。与上面两种宏一样,在定义中使用Rust代码来操作TokenStream,例如我们想定义一个解析SQL语句的宏: #[proc_macro] pub fn sql(input: TokenStream) -> TokenStream {
  上面的宏就可以这么使用sql!() let sql = sql!(SELECT * FROM posts WHERE id=1);

颜值喜人的百元有线耳机徕声T200大家好,好久没跟大家推荐耳机了,今天跟大家分享的是徕声科技出品的一款百元内的入门级HiFi音乐耳机,这个品牌别的不说,在外观设计上很有自己的独特见解,在外观方面很符合我口味,下面就LG官宣正式退出手机业务4月5日上午,韩国LG电子召开理事会,正式宣布停止其手机业务,此前早有预告,所以这次官宣没有引起太大的波澜。作为一家较早进入手机领域的电子企业,LG高光时刻的表现还是十分不错的,其美国监管机构公布特斯拉失控调查结果美国国家公路交通安全管理局(NHTSA)是美国政府部门汽车安全的最高主管机关,是美国运输部下的一个执行机构,其宗旨是保护生命防止伤害,减少车辆撞击。NHTSA缺陷调查办公室在接到客中国三大运营商退市纽交所NO在2021年的最后时间,纽交所发出一则声明,根据纽交所的声明,中国的三家电信运营商将在1月7日至1月11日期间退市。此消息一出,整个业界为之震惊,甚至有行业人士认为这是彻底疯狂了,HUGOBOSS中国总经理来自施华洛世奇Dior任命首席传讯和形象官HUGOBOSS10月25日,全球奢侈品时尚集团HUGOBOSS(雨果博斯)任命孙珏女士(JudithSun)为中国区董事总经理。她将领导公司在此最具活力的市场的新战略执行,积极提2021华丽志上海沙龙全景报道聚焦中国品牌成长和全球时尚投资2021年10月12日13日上海时装周期间,华丽志在上海新天地连续举办了两场线下行业沙龙活动,聚焦中国品牌成长和全球时尚投资两个重要课题,邀请时尚产业的创业者投资人和高级管理者共聚直播报名好瓶COO对话中国品牌主理人第15期华丽志线上音视频栏目对话中国品牌主理人,邀请中国最具潜力的品牌创始人,分享他们的一手经验和深层思考。好瓶也与不同领域的企业跨界合作,比如与可口可乐中国推出联名款24包,与中国航天文特写雪山沙漠盐湖中国品牌如何为时装大秀选址?如何为大秀选址?正在成为越来越多时尚品牌苦思冥想的问题。秀场所处的环境虽然是无声的背景,却为品牌的表达提供了最好的坐标和注解。翻修前的巴黎大皇宫一直是法国奢侈品牌Chanel(香奈深度中国时尚新品牌加速涌现,这六个最新趋势不容错过在今天的中国时尚市场,海量新品牌正不断涌现,而人头攒动热闹非凡的上海时装周,正是近距离观察这些新品牌不容错过的一个窗口。截止到10月17日,2022春夏上海时装周完成了超百场男装女高通最新5G芯片依然是业界第一国内现在都在欢度春节,但是西方国家是没有春节这一节日的,2020年联发科在5G领域一度超过一直手机芯片领域的业界老大高通!联发科2020年下半年发布了全球首款基于5nm工艺的5G调苹果春季发布会终于定了众多果粉翘首以盼的春季发布会终于确定了。苹果公司在今天凌晨向媒体发出2021年春季特别活动邀请函,确定将于美国当地时间4月20日(北京时间4月21日)通过线上形式举行活动。此次发布
新加坡已部署机器人巡逻新加坡以严格的法律和遍布整个城市的监控。未来,它也可能会部署机器人来留意违反规则的人事实上,新加坡已经开始测试一个名为Xavier的机器人,让他们在人流量大的公共区域巡逻,从而让他CPUGPUAPU都是些什么?小白科普大家现在用手机用电脑,经常会听到CPUGPU等名词,但是很多人并不清楚都是什么?都用来干什么?甚至近些年还流行出APU等代名词,具体又有哪些区别?01hr计算机的大脑CPUCPU的顶配6999元全系蔡司T镀膜加持vivoX70系列正式发布9月9日晚间,vivo召开线上新品发布会,正式带来了预热许久的X系列旗舰新机X70X70Pro和X70Pro三款产品。作为X70系列中的顶配机型,X70Pro采用了一块由三星定制的看完后让你成为武松,手把手教你打死Java中的纸老虎泛型,其实算是Java当中比较难的语法了,很多人一开始都对其一知半解,也很害怕阅读带泛型的源码,虽然看起来语法很难,但当你理解后会觉得很简单,其实只是一个纸老虎罢了。下面,我将会用华为Mate50Pro超级3K曲面屏概念设计,后置徕卡5摄和2寸副屏随着苹果新品手机的曝光,华为下一代的旗舰手机华为Mate50Pro也引起了外界的更多关注。其实很多消费者比较关注的是未来华为Mate50Pro的硬件配置如何,因为华为Mate50P工信部晒新能源补贴账单,5年共329亿元近日,工信部发布关于20162020年度新能源汽车推广应用补助资金清算审核初审情况的公示,显示自2016年至2020年,按整车企业取整后补贴资金共329。46亿元。其中,比亚迪北汽携号转网操作方法最近我要抛弃移动,投入电信的怀抱了。主要原因是电信话费不要钱,我绑个副卡呲牙,不是什么服务不好的啥的,看看我也用移动很久了,5365天。我是移动的号码,我转电信只要拿到授权码,我可国内公司告苹果侵权胜诉iPhone13可能面临禁售?去年8月,小i机器人向上海市高级人民法院提出诉讼,要求苹果公司停止有关语音助手Siri的专利侵权,并赔偿人民币100亿元人民币。最终终审判决苹果电脑贸易(上海)有限公司败诉,确认小放大招!奔驰电动车扎堆来了!慕尼黑车展正在如火如荼地进行中,作为东道主,奔驰也毫不吝啬,此次发布了多款纯电动车,接下来,我们就带大家去了解一下。奔驰EQG概念车一句话点评电动版大G来了!先上一道硬菜,在本届慕新突破!1000公里的纯电动车马上要量产了目前市场上,大家常见的新能源车主要有混动和纯电,混动里程主要有55km80km100km120km等,纯电续航里程主要分布为300600km,真正敢量产宣称700km以上的纯电动车没有木星的庇护,地球会怎么样?太阳系八大行星(以前冥王星也算,后来被开除了)里,论个头地球只是个小兄弟。地球虽然有大气层的保护,但也就能对付直径几十公里以下小型天体,10公里直径的小行星撞击地球就将恐龙直接抹掉