前言
在 Rust 中,macro_rules! 是一種宣告宏,允許在編譯時生成程式碼。
一、列印文字
示例: macro_rules!:宣告瞭一個宏,宏的名字是 hello。呼叫 hello!() 時,編譯器在編譯時會展開宏,生成 println!("Hello, world!");
macro_rules! hello {
() => {
println!("Hello, world!");
};
}
fn main() {
hello!(); // 呼叫宏
}
二、帶引數的宏
示例: $num:expr:宏引數 $num 是一個表示式(expr 是 Rust 中的模式型別,用於匹配任意表示式)。
macro_rules! print_num {
($num:expr) => {
println!("The number is: {}", $num);
};
}
fn main() {
print_num!(10); // 輸出:The number is: 10
}
三、帶多個引數的宏
示例: $($x:expr),:$x 匹配表示式,$() 表示重複匹配模式, 表示可以匹配零個或多個這樣的表示式。
macro_rules! sum {
($($x:expr),*) => {
{
let mut total = 0;
$(
total += $x;
)*
total
}
};
}
fn main() {
let result = sum!(1, 2, 3, 4, 5); // 結果為15
println!("Sum is: {}", result);
}
四、分支宏
示例: 根據傳入的標記(first 或 second),匹配到不同的模式,生成不同的程式碼。
macro_rules! choose {
(first) => {
println!("You chose the first option.");
};
(second) => {
println!("You chose the second option.");
};
}
fn main() {
choose!(first); // 輸出:You chose the first option.
choose!(second); // 輸出:You chose the second option.
}
五、遞迴宏
示例:宏可以遞迴地呼叫自身,直到匹配結束。
macro_rules! write_list {
() => {}; // 空列表的情況
($first:expr $(, $rest:expr)*) => {
println!("{}", $first);
write_list!($($rest),*); // 遞迴呼叫宏
};
}
fn main() {
write_list!("apple", "banana", "cherry");
// 輸出:
// apple
// banana
// cherry
}
六、宏中的程式碼塊
示例: ident 是用於匹配識別符號的模式。宏將根據傳入的識別符號(如 foo 和 bar)生成不同的函式。
macro_rules! create_function {
($name:ident) => {
fn $name() {
println!("You called {}()", stringify!($name));
}
};
}
create_function!(foo);
create_function!(bar);
fn main() {
foo(); // 輸出:You called foo()
bar(); // 輸出:You called bar()
}
七、總結與反思
macro_rules! 是 Rust 的宣告宏,使用模式匹配來生成程式碼。