学习rust语言,必然不可避免要了解和熟悉宏。rust语言的宏功能非常强大,通过合理的编写利用宏,可以简化程序代码,也少写很多代码。今天我们先从宏的基本编写方法macro_rules开始:
1,格式
macro_rules! $name {$rule0 ;$rule1 ;$rule2 ;// …$ruleN ;
}
大括号里面的规则(rule)有点类似rust中的match匹配,匹配其中的一条rule,则用其中的内容生成具体代码。
规则(rule)涉及到一个匹配格式:($pattern)和{$expansion}可以是任何类型的组,其中的括号和大括号根据官网说法是约定俗成。
($pattern) => {$expansion}
2,简单测试
我们编写一个简单宏进行以下测试
#[macro_export]
macro_rules! add10 {($a:expr) => {{$a+10}};
}fn testadd(){println!("the add10 value is {}", add10!(10));
}
我们编写一个对于输入数字加10的宏,我们输入10,最终打印输出为20.
3,详解
3.1,宏捕获
规则中可以通过多种多样的语法进行匹配捕获,匹配符合时,将运行后续语句,并将结果传输到一个变量中,最终输出。
规则捕获中,以美元符号($)开始,后跟:符号,最后跟捕获类型。捕获类型有如下这些:
item
:一个项目,如函数、结构体、模块等。block
:一个块(即一个语句块和/或一个表达式,用大括号括起来)stmt
:一个声明pat
:模式expr
:表达式ty
:类型ident
:标识符path
: 路径(例如 , , , ...)foo
::std::mem::replace
transmute::<_, int>
meta
:一个元项;里面的东西和属性#[...]
#![...]
tt
:单个标记树
下面这个宏,它将输入捕获为表达式(rust本来就是表达式语言),我们写的add10宏也是将输入捕获为表达式:
macro_rules! one_expression {($e:expr) => {...};
}
例如我们也可以写一个对于任何输入数字进行与100相乘的宏mul100
macro_rules! mul100 {($a:expr) => {{$a*100}};
}
我们也可以捕获多个输入:
macro_rules! moreadd {($a:expr, $b:expr, $c:expr) => {{$a+$b+$c}};
}
3.2,重复项
模式(pattern)中可以包含重复项,而通过重复项的方法,我们可以匹配和捕获多个输入,这样通过宏极大的扩展了程序的功能。
重复项一般通过$(.....) sep rep的形式出现
$
是 Literal Dollar 代币。( ... )
是重复的括号分组模式。sep
是可选的 separator token。常见示例包括 和 。,
;
rep
是必需的重复控件。目前,这可以是 (表示零个或多个重复) 或 (表示一个或多个重复) 。您不能编写 “zero or one” 或任何其他更具体的计数或范围。*
+
下面我们通过官网的介绍说明的类似vec!宏的编写方法:
#[macro_export]
macro_rules! my_vec {( $( $x:expr ),* ) => {{let mut temp_vec = Vec::new();$(temp_vec.push($x);)*temp_vec}};
}fn test_micro(){let v = my_vec!(1,2,3,4);for i in v{println!("the is is {}",i);}
}