# eg1:
| macro_rules! my_macro { |
| |
| ($arg1:expr, $arg2:expr) => { |
| |
| ($arg1) + ($arg2) |
| }; |
| } |
| |
| fn main() { |
| |
| let x = my_macro!(1, 2); |
| println!("{}", x); |
| } |
# eg2:
| macro_rules! c_max { |
| ($x:expr, $y:expr) => { |
| if $x > $y { |
| $x |
| } else { |
| $y |
| } |
| }; |
| } |
| |
| fn main() { |
| let a = 3; |
| let b = 5; |
| let max = c_max!(a, b); |
| println!("The max value is {}", max); |
| } |
# eg3:
| macro_rules! SQUARE { |
| ($x:expr) => { |
| ($x) * ($x) |
| }; |
| } |
| |
| fn main() { |
| let x = 2; |
| let result = SQUARE!(x + x); |
| println!("The square of {} is {}", x + x, result); |
| } |
# eg4:
| macro_rules! print_fmt { |
| ($fmt:expr) => (print!("{}", $fmt)); |
| ($fmt:expr, $($arg:tt)*) => (print_fmt_args!($fmt, $($arg)*)); |
| } |
| |
| macro_rules! print_fmt_args { |
| ($fmt:expr, $($arg:tt)*) => <!--swig0-->; |
| } |
| |
| fn main() { |
| let name = "Rust"; |
| let age = 5; |
| let pi = 3.14159; |
| |
| print_fmt!("Hello, my name is {} and I'm {} years old. PI is {:.2}\n", name, age, pi); |
| } |
# exp5:
这个例子是一个使用 Rust 声明宏来实现一个简单的链表的例子。这个宏叫做 list!
,它可以帮助我们生成一个链表。这个宏支持三种不同的用法:
list!()
:生成一个空链表( Nil
);list!(expr)
:生成一个只有一个元素的链表,元素的值为 expr
;list!(expr1, expr2, ..., exprn)
:生成一个包含多个元素的链表,元素的值分别为 expr1
到 exprn
。
在这个例子中,我们使用了 Box
来实现链表的尾部指针,以避免使用递归结构导致的栈溢出问题。
| macro_rules! list { |
| () => { |
| Nil |
| }; |
| ($e:expr) => { |
| Cons($e, Box::new(Nil)) |
| }; |
| ($e:expr, $($tail:tt)*) => <!--swig1-->; |
| } |
| |
| enum List { |
| Cons(i32, Box<List>), |
| Nil, |
| } |
| |
| fn main() { |
| let list = list![1, 2, 3]; |
| println!("{:?}", list); |
| } |
# exp6:
这个例子实现了一个计算平均数的宏,可以接受任意数量的参数,忽略空值,计算非空值的平均值并返回。宏使用了 Rust 的模式匹配语法,同时也用到了 Rust 的闭包和类型推导等特性。
| macro_rules! calculate { |
| ($($args:tt)*) => <!--swig2-->; |
| } |
| |
| fn main() { |
| let result = calculate!(Some(10), None, Some(20), Some(30), None, Some(40)); |
| println!("{:?}", result); |
| } |
# exp7:
这个宏定义了一个结构体和一组方法,其中方法可以有不同的参数和返回值。通过使用宏规则中的 $($method:ident ($($param:ident : $type:ty),*) -> $ret:ty)*
,可以将方法名称、参数列表和返回值类型分别提取出来,然后使用嵌套的宏规则实现方法的实现。这个例子相比之前的例子更加复杂,宏规则中涉及到了宏的嵌套、可变参数和泛型类型等高级特性。
| macro_rules! define_struct_and_methods { |
| ($name:ident, $field:ident, $($method:ident ($($param:ident : $type:ty),*) -> $ret:ty)*) => { |
| struct $name { |
| $field: i32, |
| } |
| |
| impl $name { |
| fn new($field: i32) -> Self { |
| $name { $field } |
| } |
| $($( |
| fn $method(&self, $($param : $type),*) -> $ret { |
| |
| } |
| )*)* |
| } |
| }; |
| } |
| |
| define_struct_and_methods!( |
| MyStruct, |
| my_field, |
| method1() -> i32, |
| method2(x: i32) -> bool, |
| method3(x: i32, y: i32) -> String |
| ); |
# exp8:
这是一个用于生成哈希映射的声明宏。这个宏可以接受 1 个或多个键值对参数,每个键值对之间使用逗号分隔,键和值之间使用 =>
分隔。
这个宏会生成一个 HashMap
,其中包含三个键值对。如果调用时只传入一个参数,则该参数必须是偶数个,因为每个键都必须有一个对应的值。如果键或值是表达式,则需要用括号将它们括起来。
这个宏的实现使用了 Rust 中的 std::collections::HashMap
,并且使用了一些比较复杂的宏技巧来计算参数个数,并生成一个指定容量的哈希映射。
| macro_rules! map { |
| (@single $($x:tt)*) => (()); |
| (@count $($rest:expr),*) => (<[()]>::len(&[$(map!(@single $rest)),*])); |
| ($($key:expr => $value:expr,)+) => { map!($($key => $value),+) }; |
| ($($key:expr => $value:expr),*) => { |
| { |
| let _cap = map!(@count $($key),*); |
| let mut _map = ::std::collections::HashMap::with_capacity(_cap); |
| $( |
| let _ = _map.insert($key, $value); |
| )* |
| _map |
| } |
| }; |
| } |
| |
| let m = map! { |
| "a" => 1, |
| "b" => 2, |
| "c" => 3, |
| }; |