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 声明式导航和编程式导航 共同点: 都能进行导航,都可以触发路由,实现组件切 ...
随机推荐
- 管理WEB服务器文件的WebDAV协议&HTTP大跃进--QUIC与HTTP30&WEB安全攻击概述
管理WEB服务器文件的WebDAV协议 WebADV协议 WEBDAV追加方法 WeDAV请求示例 HTTP大跃进--QUIC与HTTP30 QUIC&HTTP3.0 HTTP2.0的问题 队 ...
- [JAVA/Maven/IDEA]解决JAR包冲突
1 前言 想必这个问题,诸多同仁都遇到过. 很不凑巧,这段时间咱也屡次撞上这问题好几次了. 因此,实在是有必要说说怎么解决好这问题了0.0 2 诊断:包冲突的异常信息特征 [类定义未发现错误] NoC ...
- linux下的一道堆上的格式化字符串漏洞题分析分享
简单分享一下解题过程. 下载题目,里面有三个文件,如图: DockerFIle文件: net.sh文件: shell文件是一个elf,文件情况: 64位,Full RELO,NX,PIE 丢进IDA看 ...
- 涨姿势了,有意思的气泡 Loading 效果
今日,群友提问,如何实现这么一个 Loading 效果: 这个确实有点意思,但是这是 CSS 能够完成的? 没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元 ...
- RDIFramework.NET开发框架在线表单设计助力可视化快速开发
1.概述 RDIFramework.NET在线表单是易于使用的在线表单设计组件,为快速开发企业应用,流程应用等快速在线设计表单和收集数据提供支持.例如可设计一些订单信息表.客户信息表等,是所见即所得的 ...
- 使用Dockerfile构建容器镜像
Dockerfile官方文档: https://docs.docker.com/engine/reference/builder/ 获取容器镜像的方法 容器镜像是容器模板,通过容器镜像才能快速创建容器 ...
- ROS用hector创建地图
ROS用hector创建地图 连接小车 ssh clbrobot@clbrobot 激活树莓派 roslaunch clbrobot bringup.launch 打开hector_slam 重新开终 ...
- Node.js入门学习笔记
NodeJs是js的运行时,意味着可以在浏览器外运行js.可以使用nodejs来构建服务器端应用.CLI应用.Web API,甚至用electron构建桌面端应用. 使用nvm来管理node版本. 在 ...
- vue3.0
https://www.yuque.com/gdnnth/vue-v3 http://www.liulongbin.top:8085/#/ https://www.yuque.com/woniuppp ...
- [Pytorch框架] 2.1.1 PyTorch 基础 : 张量
文章目录 PyTorch 基础 : 张量 张量(Tensor) 基本类型 Numpy转换 设备间转换 初始化 常用方法 PyTorch 基础 : 张量 在第一章中我们已经通过官方的入门教程对PyTor ...