# eg1:

macro_rules! my_macro {
    // 定义宏函数
    ($arg1:expr, $arg2:expr) => {
        // 定义宏函数体,此处为求两个参数的和
        ($arg1) + ($arg2)
    };
}
fn main() {
    // 调用宏函数
    let x = my_macro!(1, 2);
    println!("{}", x);  // 输出 "3"
}

# 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! ,它可以帮助我们生成一个链表。这个宏支持三种不同的用法:

  1. list!() :生成一个空链表( Nil );
  2. list!(expr) :生成一个只有一个元素的链表,元素的值为 expr
  3. list!(expr1, expr2, ..., exprn) :生成一个包含多个元素的链表,元素的值分别为 expr1exprn

在这个例子中,我们使用了 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 {
                // method implementation here
            }
            )*)*
        }
    };
}
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,
};