服装电子商务网站版式设计WordPress评论加入ip
服装电子商务网站版式设计,WordPress评论加入ip,百度竞价推广是什么工作,网站title的作用前言
rust 学习曲线非常陡峭#xff0c;但是基本语法也还算挺好理解#xff0c;自动内存管理有点类似智能指针#xff0c;基本看一下语法入门就可以大概理解#xff0c;但是唯独宏很难理解#xff0c;语法非常晦涩。但是功能非常强大。声明宏类似于c语言的宏处理#xf…前言
rust 学习曲线非常陡峭但是基本语法也还算挺好理解自动内存管理有点类似智能指针基本看一下语法入门就可以大概理解但是唯独宏很难理解语法非常晦涩。但是功能非常强大。声明宏类似于c语言的宏处理但是功能更强大。过程宏则类似于Android的注解编程自定义AbstractProcessor但是实现更优雅。 下面记录一下宏处理的一些特点
正文
目前主流的文章都是翻译自官方文档或者取部分Rust语言圣经关键的部分特性就确实只有rust宏详解中非常详细的介绍这里简要记录一下特点
声明宏
声明宏主要是替代主要是通过简单的模式匹配然后进行操作这貌似非常容易处理面向对象的工厂模式或者解决方法多参数操作比如
macro_rules! vec {() ($crate::__rust_force_expr!($crate::vec::Vec::new()));($elem:expr; $n:expr) ($crate::__rust_force_expr!($crate::vec::from_elem($elem, $n)));($($x:expr), $(,)?) ($crate::__rust_force_expr!([_]::into_vec(// This rustc_box is not required, but it produces a dramatic improvement in compile// time when constructing arrays with many elements.#[rustc_box]$crate::boxed::Box::new([$($x),]))));
}这就是根据不同的匹配模式的前半部分替换成后半部。比如无参数的vec。因为这是系统接口这里不在详细介绍操作只介绍匹配
()是无参构造函数。($elem:expr; $n:expr)这是匹配模式类似vec![1;5],这是创造一个size是5的值是1的vec。这个是匹配vec![1, 2, 3]这是构造一个内容是1、2、3的vec
第二个匹配模式中$elem是为匹配的内容命名方便后面使用expr一个表达式 (expression)指明匹配的元素就不用解释就是字面值。$n:expr同样道理。 第二个匹配则稍微复杂一些这里则用的是循环模式。循环是通过$(....)来指明的括号内为循环内容为了方便阅读则需要有分隔符和循环次数这里是通过定义分隔符定义循环至少一次。$(,)?又是一个循环循环内容则是。而循环一次则是最多一次。
所有的语句如下
block一个块比如一块语句或者由大括号包围的一个表达式 expr一个表达式 (expression) ident一个标识符 (identifier)包括关键字 (keywords) item一个条目比如函数、结构体、模块、impl 块 lifetime一个生命周期注解比如 foo、static literal一个字面值比如 “Hello World!”、3.14、‘’ meta一个元信息比如 #[…] 和 #![…] 属性内部的东西 pat一个模式 (pattern) path一条路径比如 foo、::std::mem::replace、transmute::_, int stmt一条语句 (statement) tt单棵标记树 ty一个类型 vis一个可能为空的可视标识符比如 pub、pub(in crate)
循环则如下
反复捕获的一般形式为 $ ( … ) sep rep。
$ 是字面上的美元符号标记 ( … ) 是被反复匹配的模式由小括号包围。 sep 是可选的分隔标记。它不能是括号或者反复操作符 rep。常用例子有 , 和 ; 。 rep 是必须的重复操作符。当前可以是
?表示最多一次重复所以此时不能前跟分隔标记。*表示零次或多次重复。表示一次或多次重复。
过程宏
分为三类
派生宏Derive macro用于结构体struct、枚举enum、联合union类型可为其实现函数或特征Trait。属性宏Attribute macro用在结构体、字段、函数等地方为其指定属性等功能。如标准库中的#[inline]、#[derive(…)]等都是属性宏。函数式宏Function-like macro用法与普通的规则宏类似但功能更加强大可实现任意语法树层面的转换功能。
声明宏需要解析传入的参数进行匹配而过程宏则需要自己解析传入的内容然后进行补充生成代码。这里需要解析TokenStream举个例子就是用宏为一个结构体实现构建者模式。
#[derive(Builder)]
struct Command {// ...
}最麻烦的是如何实现Builder
#[derive(Builder)]
struct Command {input_paht: String,// ...
}pub fn derive_builder(input: TokenStream) - TokenStream {let input parse_macro_input!(input as DeriveInput); // 解析input为 DeriveInput类型let input_ident input.ident; // 获取原始类名let ident_builder format_ident!({}Builder, input_ident.to_string()); // 拼接builder类名if let Data::Struct(r) input.data { // 处理结构体let fields r.fields;// 结构体属性声明let builder_fields map_fields(fields, mut |(ident, ty)| {quote!(#ident: Option#ty,) });// 为builder增加set函数let builder_set_fields map_fields(fields, mut |(ident, ty)| {quote!(pub fn #ident(mut self, value: #ty) - Self {self.#ident Some(value);self}) });// 获取builder的属性值let builder_lets map_fields(fields, mut |(ident, _)| {quote!(let #ident self.#ident.ok_or(format!(field {:?} not set yet, stringify!(#ident),))?;)});// 初始化时的默认值let builder_fields_values map_fields(fields, mut |(ident, _)| {quote!(#ident,)});quote!(impl #input_ident {pub fn builder() - #ident_builder {#ident_builder::default()}}#[derive(Default)]pub struct #ident_builder {#builder_fields}impl #ident_builder {#builder_set_fieldspub fn build(self) - Result#input_ident, String {#builder_letsOk(#input_ident{ #builder_fields_values })}}).into()} else {// 不支持非struct类型quote!().into()}
}fn map_fieldsF(fields: Fields, mapper:mut F) - TokenStream2
whereF: FnMut((Optionproc_macro2::Ident , Type)) - TokenStream2,
{let fs fields.iter().map(|field| mapper((field.ident ,field.ty)) );let stream2 TokenStream2::from_iter(fs);stream2
}这里为Command实现了builder方法如下
impl Command{pub fn builder() - CommandBuilder{CommandBuilder::default()}
}pub struct CommandBuilder{input_path: String,
}impl CommandBuilder{pub fn (mut self, value: String) - Self {self.input_path Some(value);self}pub fn build(self) - ResultCommand, String {let input_path self.input_path.ok_or(format!(field {:?} not set yet, stringify!(input_path),))?;Ok(Command{ input_path })}}属性宏则可以传入参数让控制更自由一些这里就不在详细介绍 函数式宏则相对比较简单类似声明宏但是可以不去匹配规则更自由功能更强大。
解析TokenStream需要依赖一些库这比较复杂就不在详细介绍。要结合自己代码需求慢慢理解。
分析工具
cargo.exe install cargo-expandcargo.exe expand后记
rust实在是复杂这里解释一些语法规则以后遇到问题再补充。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88133.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!