Rust 声明式宏中的 Metavariables 有哪些

官方文档确实写得很好,但是缺少一些风味,容易催眠
还是直接看例子更爽一些,通常我们可以从示例代码中之间看出官方文档要表达的意思,而且很多时候我们可以直接在示例代码的基础上改一改,就能满足我们自己的定制化需求。越抽象的东西,越是如此
item
An item is a component of a crate. Items are organized within a crate by a nested set of modules. Every crate has a single "outermost" anonymous module; all further items within the crate have paths within the module tree of the crate.
There are several kinds of items:
- modules
- extern crate declarations
- use declarations
- function definitions
- type definitions
- struct definitions
- enumeration definitions
- union definitions
- constant items
- static items
- trait definitions
- implementations
- extern blocks
可以把整个 crate 比作一个 struct,这个 struct 里面的每一个 field 都是一个 item
这些 item 包括每一个 struct, fn, mod 的定义...
macro_rules! test_item {
($x: item) => {
// #[derive(Debug)]
$x
}
}
test_item!(#[derive(Debug)] struct A{a: i32});
test_item!(fn foo(){println!("foo");});
test_item!(mod ma{});
let a = A{ a: 9};
println!("a: {:?}", a); // 输出 a: A { a: 9 }
foo(); // 输出 foo
block
block 是匿名的命名空间作用域(anonymous namespace scope),就是以 { 开始 以 } 结束的整个块
macro_rules! test_block {
($x: block) => {
$x
}
}
test_block!({
println!("block");
});
stmt
A statement is a component of a block, which is in turn a component of an outer expression or function
一个 stmt 可以是一个前面的 [item](## item), 或是 let statement, 或是 expression statement, 或是宏调用
macro_rules! test_stmt {
($x: stmt) => {
$x
}
}
// let statement
test_stmt!(let state = 8);
println!("state: {}", state);
// item
test_stmt!(#[derive(Debug)] struct B{b: i32});
// expression statement
test_stmt!{
if true {
1
} else {
2
}
};
// Macro Invocation
test_stmt!{
println!("Macro Invocation")
};
pat_param
用来 pattern match 的 param, 匹配一个 pattern, 像 match 内 => 左边的那些东西
pat_param 默认不匹配 or-pattern: 0 | 1 | 2
macro_rules! test_pat_param {
($x: pat_param) => {
$x
}
}
struct Person {
car: Option<String>,
age: u8,
name: String,
gender: u8,
gfs: [String; 3],
}
let person = Person {
car: Some("bmw".into()),
age: 18,
name: "hansomeboy".into(),
gender: 1,
gfs: ["Lisa".into(), "Jennie".into(), "Rosé".into()],
};
if let test_pat_param!(
Person {
car: Some(_),
age: person_age @ 13..=19,
name: ref person_name,
gfs: ref whole @ [.., ref last],
..
}
) = person {
println!("{} has a car and is {} years old, and his last GF is {}.", person_name, person_age, last);
}
macro_rules! test_or_pattern {
($($x: pat_param)*) => ();
}
test_or_pattern!{
Some(_)
Foo{x}
// error: no rules expected the token `|`
// 0 | 1 | 2
}
输出: hansomeboy has a car and is 18 years old, and his last GF is Rosé.
pat
用来匹配任意类型的 pattern, 包括 or-pattern: 0 | 1 | 2
macro_rules! test_pat {
($($pat:pat)*) => ();
}
test_pat! {
"literal"
_
0..5
ref mut PatternsAreNice
0 | 1 | 2 | 3
}
expr
一个表达式 Expression
macro_rules! test_expr {
($($x: expr)*) => ();
}
test_expr!{
"hello" // LiteralExpression
42 // LiteralExpression
a::b::c // PathExpression
a * b + c // OperatorExpression
&a
*a
-a
a = b
a += b
a || b && c
a & b | c
(a+b) - c
["a"] // ArrayExpression
a[b][c] // IndexExpression
("world", 42) // TupleExpression
tuple.0 // TupleIndexingExpression
Point {x: 1.0, y: 2.0} // StructExpression
foo() // CallExpression
"3.14".parse() // MethodCallExpression
foo().await // AwaitExpression
bar.await
hello.world // FieldExpression
move|x,y| -> () {} // ClosureExpression
async move {} // AsyncBlockExpression
0..10 // RangeExpression
(_, a) // UnderscoreExpression
vec![1,2,3] // MacroInvocation
continue 'hello // ContinueExpression
break 'hello // BreakExpression
return 42 // ReturnExpression
{} // BlockExpression
#[cfg("hello")]{}
unsafe {} // UnsafeExpression
if condition {} // IfExpression
if let a=b {} // IfLetExpression
match x {} // MatchExpression
}
ty
一个类型 Type
macro_rules! test_ty {
($($x: ty)*) => ();
}
test_ty! {
u32
bool
char
str
String
[u8; 128]
(u32, bool)
&[u8]
Hello // User-defined types
fn(u8, u8) -> ()
&mut reference
*mut pointer
*const pointer
dyn Trait // Trait Object
impl Trait // Impl Trait
}
ident
一个标识符(用来标识变量、函数、类、对象或其他程序实体的名称) an IDENTIFIER_OR_KEYWORD or RAW_IDENTIFIER
macro_rules! test_ident {
($($x: ident)*) => ();
}
test_ident! {
foo
_identifier
r#true // raw identifier
深圳
}
path
macro_rules! test_path {
($($x: path)*) => ();
}
test_path! {
a::b::c
self::a::<b>::c
::std::time::Instant::now()
}
tt
标记树(token tree) 是一种介于标记 (token) 与 AST(abstract syntax tree) 之间的东西
几乎所有的 token 都是 token tree 的叶子节点(leaf node), 只有被 (...), [...] 和 {...} 包裹在一起的一组一组的 tokens 不是叶子节点
a + b + (c + d[0]) + e
会被解析成下面的 token tree:
«a» «+» «b» «+» «( )» «+» «e»
╭────────┴──────────╮
«c» «+» «d» «[ ]»
╭─┴─╮
«0»
可以看出 token tree 的 root 节点其实是第一行的这一整组 token: «a» «+» «b» «+» «( )» «+» «e», 而不是单一的 node
而 AST 会生成下面这种只有一个 root 节点的数状结构:
┌─────────┐
│ BinOp │
│ op: Add │
┌╴│ lhs: ◌ │
┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐
│ Var │╶┘ └─────────┘ └╴│ BinOp │
│ name: a │ │ op: Add │
└─────────┘ ┌╴│ lhs: ◌ │
┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐
│ Var │╶┘ └─────────┘ └╴│ BinOp │
│ name: b │ │ op: Add │
└─────────┘ ┌╴│ lhs: ◌ │
┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐
│ BinOp │╶┘ └─────────┘ └╴│ Var │
│ op: Add │ │ name: e │
┌╴│ lhs: ◌ │ └─────────┘
┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐
│ Var │╶┘ └─────────┘ └╴│ Index │
│ name: c │ ┌╴│ arr: ◌ │
└─────────┘ ┌─────────┐ │ │ ind: ◌ │╶┐ ┌─────────┐
│ Var │╶┘ └─────────┘ └╴│ LitInt │
│ name: d │ │ val: 0 │
└─────────┘ └─────────┘
macro_rules! test_tt {
($($x: tt)*) => {
println!("test_tt:");
$( println!("{:?}", stringify!($x)); )*
}
}
test_tt! {
(a + b + (c + d[0]) + e)
[a + b + (c + d[0]) + e]
{a + b + (c + d[0]) + e}
}
test_tt! {
a + b + (c + d[2]) + e
}
输出:
test_tt:
"(a + b + (c + d [0]) + e)"
"[a + b + (c + d [0]) + e]"
"{ a + b + (c + d [0]) + e }"
test_tt:
"a"
"+"
"b"
"+"
"(c + d [2])"
"+"
"e"
meta
用来匹配 attribute 属性
就是那些写在 struct/enum/fn 前面的 #[...] #![...]
macro_rules! test_meta {
($(#$(!)?[$meta: meta])*) => ();
}
test_meta! {
#[hello]
#![world]
#[a="b"]
}
lifetime
macro_rules! test_lifetime {
($($x: lifetime)*) => ();
}
test_lifetime! {
'a
'_
'static
}
vis
macro_rules! test_vis {
// ∨~~Note this comma, since we cannot repeat a `vis` fragment on its own
($($x: vis,)*) => ();
}
test_vis! {
,
pub,
pub(crate),
pub(super),
pub(self),
pub(in crate::a::b),
}
literal
macro_rules! test_literal {
($($x: literal)*) => ();
}
test_literal! {
0
b'x'
'x'
"hello"
true
}
Rust 声明式宏中的 Metavariables 有哪些的更多相关文章
- Spring -12 -声明式事务及完整的XML配置文件信息 -声明式事务中的相关属性(tx:advice的标签)
1.编程式事务: 1.1由程序员编程事务控制代码. 1.2OpenSessionInView 就属于编程式事务: session.commit()和rollback() 2.声明式事务: 2.1事务控 ...
- Jenkins 在声明式 pipeline 中并行执行任务
在持续集成的过程中,并行的执行那些没有依赖关系的任务可以缩短整个执行过程.Jenkins 的 pipeline 功能支持我们用代码来配置持续集成的过程.本文将介绍在 Jenkins 中使用声明式 pi ...
- mysql事务管理及spring声明式事务中主动异常抛出使数据库回滚
mysql的引擎常用的有两个,一个MyISAM,另一个是InnoDB,mysql默认的为MyISAM,而InnoDB才是支持事务的.所以一般需要修改下,如何修改就不说了. 事务需要依赖数据库,好久没使 ...
- spring 声明式事务中try catch捕获异常
原文:http://heroliuxun.iteye.com/blog/848122 今天遇到了一个这个问题 最近遇到这样的问题,使用spring时,在业务层需要捕获异常(特殊需要),当前一般情况下不 ...
- Spring声明式事务不回滚问题
疑问,确实像往常一样在service上添加了注解 @Transactional,为什么查询数据库时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚.于是就对相关代码进行了 ...
- Jenkins pipeline声明式语法
目录 一.最简结构 二.简单例子 一.最简结构 pipeline { agent any stages { stage('pull') { st ...
- Spring中的事物管理,用 @Transactional 注解声明式地管理事务
事物: 事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的 完整性和 一致性. 事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用 事务的四 ...
- C#中手工进行声明式验证,从此远离if验证
今天在一个ASP.NET MVC Controller Action中写代码时,需要对ViewModel的字段进行验证.但这个Action处理的是手工编写的ajax请求(不是表单提交),无法使用ASP ...
- 声明式RESTful客户端在asp.net core中的应用
1 声明式RESTful客户端 声明式服务调用的客户端,常见有安卓的Retrofit.SpringCloud的Feign等,.net有Refit和WebApiClient,这些客户端都是以java或. ...
- vue中声明式导航和编程式导航
官方文档:https://router.vuejs.org/zh-cn/essentials/navigation.html 声明式导航和编程式导航 共同点: 都能进行导航,都可以触发路由,实现组件切 ...
随机推荐
- 逍遥自在学C语言 | 第一个C语言程序 九层之台起于垒土
一.人物简介 第一位闪亮登场,有请今后会一直教我们C语言的老师 -- 自在. 第二位上场的是和我们一起学习的小白程序猿 -- 逍遥. 二.C语言简介 C语言是一种高级语言,运行效率仅次于汇编,支持跨平 ...
- [灾备]独立磁盘阵列(RAID)技术
本文是对3个月前临时出差前往客户现场,安装交付我司大数据产品时使用的一项硬件级的灾备技术的简要复盘. 1 独立磁盘阵列--RAID:概述 1.1 定义 RAID := Redundant Arrays ...
- [Linux]常用命令之【tar/zip/unzip/gzip/gunzip】
1 tar .tar与.gz有什么联系与区别? .tar 只是进行打包,并没有压缩. 则: 用tar-cvf进行打包 用tar-xvf进行解包. .tar.gz 是既打包又压缩 ,则: tar –cz ...
- DevOps infra | 互联网、软件公司基础设施建设(基建)哪家强?
国内公司普遍不注重基础设施建设,这也是可以理解的.吃饭都吃不饱,就别提什么荤素搭配,两菜一汤了.但也不能全说是这样,还是有很多公司投入大量的人力物力去做好公司的基建,比如很多阿里和美团的小伙伴对公司的 ...
- vue高阶函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【Spring注解驱动】(一)IOC容器
前言 课程跟的是尚硅谷雷丰阳老师的<Spring注解驱动教程>,主要用于SSM框架向SpringBoot过渡,暑假有点懒散,争取这周看完. 1 容器 Spring的底层核心功能是IOC控制 ...
- Hugging News #0414: Attention 在多模态情景中的应用、Unity API 以及 Gradio 主题构建器
每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...
- 图计算引擎分析--GridGraph
作者:京东科技 李永萍 GridGraph:Large-Scale Graph Processing on a Single Machine Using 2-Level Hierarchical Pa ...
- [Pytorch框架] 2.1.2 使用PyTorch计算梯度数值
文章目录 使用PyTorch计算梯度数值 Autograd 简单的自动求导 复杂的自动求导 Autograd 过程解析 扩展Autograd import torch torch.__version_ ...
- 关于在 springboot 中使用 @Autowired 注解来对 TemplateEngine 进行自动装配时,无法注入的问题。
前言 本文是基于江南一点雨的 Spring Boot+Vue 系列视频教程第 三 章的第三节,详情参考Spring Boot+Vue系列视频教程 在观看学习这一节时,发现当进行手动渲染 Thymele ...