Rust 1.7.0的macro宏-语法分析和使用举例
Posted teamlet
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rust 1.7.0的macro宏-语法分析和使用举例相关的知识,希望对你有一定的参考价值。
macro 宏的概念在很多语言中都有。
通常情况下,宏的机制是在预编译阶段对已经定义的宏进行替换或者 expanded 展开 ,即:把宏按照名称替换成宏的内容。
Rust 中的宏,与众不同!
Rust中的宏,也是在预编译阶段进行处理。宏不仅仅是替换内容和展开,还可以像功能函数一样,接收参数、调用其他的宏。
一、简单的宏
宏的名称和功能函数名称很像,只不过在函数名称后面有一个叹号!
一个简单的宏定义和调用:
macro_rules! say_hello{
()=>(
println!("Hello");
)
}
fn main(){
say_hello!()
}
解释一下:
macro_rules! 声明一个宏,say_hello 是宏的名字,say_hello后面是一对大括号,是宏的内容体。
大括号里面的=>前面的 ( ) 表示这个宏没有输入参数。
在这个宏内部,调用了另外一个宏 println!
在main()功能函数中调用宏。因为这个宏和调用的功能函数在一个文件中,所以不需要额外的导出和引入宏的声明。
当然,宏的内容体除了用 {}大括号之外,还可以使用 (); 和 [];
macro_rules! say_hello (
()=>(
println!("Hello");
)
);
macro_rules! say_hello [
()=>(
println!("Hello");
)
];
? 注意:
- 使用大括号的时候,大括号后面没有分号;
- 而使用()和[]的时候,后面有一个分号。
?如果大括号{}有分号;或者()和[]没有分号都会编译错误。
? 注意:
另一个需要注意的是,宏的输入参数是包含在宏内容体内的!!!
二、带参数的宏
下面定义一个带参数的宏 print_hello
macro_rules! print_hello{
($msg:expr) =>(
println!("hello{}", $msg);
)
}
fn main(){
print_hello!(",world!");
}
上面定义了一个 print_hello 宏,把上面的代码分解成 4 个部分:
第一个部分:宏声明
macro_rules! print_hello
- macro_rules! 是宏定义关键字,注意后面有 ! 叹号
- 后面跟宏的名称 这是定义宏的名称
第二部分:宏的内容边界 {一对大括号}
macro_rules! print_hello {
}
第三部分:宏的内容 -大括号中的内容
大括号中的内容被称为 macro rule 宏规则。一个宏可以包含任意(0 -n)多个 macro rule 宏规则。
($msg:expr) =>( println!("hello{}", $msg) );
($msg:expr) =>{ println!("hello{}", $msg) };
($msg:expr) =>[ println!("hello{}", $msg) ];
($msg:expr) => ( println!("hello{}", $msg); );
($msg:expr) => { println!("hello{}", $msg); };
($msg:expr) => [ println!("hello{}", $msg); ];
以上 6 句 作用完全一致!
宏规则的格式应该是这样的:
( ) => { };
( ) => [ ];
( ) => ( );
- 每个宏规则有一个 => ;
- 在 => 左面的小括号是该规则的输入参数,里面的形式是一个 叫做 matcher 匹配器;
- 在 => 右面的括号里是宏的内容,需要被执行或者替换,叫做 transcriber 转换器,可以是语句、表达式等。
以上三行代码等同。
matcher 和 transcriber 会在 后面的文章中详细说明。
前面说过,宏的参数是包含在宏内容体内的!
对比一下功能函数的声明格式:
fn fn_name(x:i32,y:u32){
}
功能函数的输入参数通过 fn_name 后面的小括号传入,参数可能是 0 个或者多个,但是所有的参数一定是在这个括号中声明。
来看看这段代码:
macro_rules! foo {
(x => $e:expr) => (println!("mode X: {}", $e));
(y => $e:expr) => (println!("mode Y: {}", $e));
}
fn main() {
foo!(x => 7);
foo!(y => 3);
}
宏的输入不是通过参数列表传入的!而是通过 match 的方式进行查找或者匹配的。
当匹配到 x => 7 ,则执行 mode X: 7
当匹配到 y => 3 ,则执行 mode Y: 3
第四部分:宏调用
print_hello!(",world!");
调用方式,使用宏名称后面加!叹号,叹号后面跟一个括号表示输入参数。
以上是关于Rust 1.7.0的macro宏-语法分析和使用举例的主要内容,如果未能解决你的问题,请参考以下文章