接下來我們要來介紹 Macro 了!
Macro 主要是用一小段程式碼來寫另一段的程式碼,這個概念跟 Meta Programming 很像,主要是避免寫過多重複的程式碼
這聽起來跟 Function 蠻像的,不過 Macro 有 Function 沒有的特性,能應用的範圍更廣,我們今天也會一併介紹!
剛剛提到 Macro 的概念跟 Meta Programming 很像,那 Meta Programming 又是什麼?
Meta Programming 主旨是在減少重複性高且繁瑣的程式碼,以更讓電腦看得懂的前提出發,將程式碼寫的更精簡,且更好維護
不過缺點在於,無法兼具易讀性,當我們寫出來的程式碼越精簡,有可能對於開發者來說會越難懂
這樣看起來 Macro 跟 Function 好像蠻像的,兩個都是將重複的事情整理起來,
不過 Macro 能做到的事情比 Function 更多,不僅可以傳遞多個參數,參數的型別也不會被限制
Macro 在編譯前就會先展開到執行緒中,而 Function 則是走一般的編譯流程並且執行
我們可以來客製化 Macro ,將重複性高的程式碼變成一個巨集,並重複使用它
macro_rules! 可以用來自定義的 macro
() 裡面可以放參數,稍後會有範例
{} 裡面的程式碼會在編譯前擴展到呼叫的 block 中
fn main() {
    macro_rules! introduction {
        () => {
            println!("My name is Ning!")
        };
    }
    introduction!()
}
> cargo run
My name is Ning!
$message $ 是 macro 的參數符號expr 指的是目前參數是什麼:為標示符號,表示我目前這個參數是什麼
除了 expr 還有其他類型等等
stmt 一個句子,例如 let x = 5;pat 一個模式,match、if let 就可以用模式expr 一個表達式,會返回值的,像是函式、運算式ty 一種類型,像是 i32 、 &str
fn main() {
    macro_rules! introduction {
        ($message:expr) => {
            println!("My name is {}!", $message)
        };
    }
    introduction!("Ning")
}
macro 放置到 main 中,在編譯前會展開,並且將參數帶入,會做出 println!("My name is {}!", "Ning") 的程式碼
> cargo run
My name is Ning!
macro 可以傳遞多個參數,並且執行多次
要讓他重複執行的話,我們需要使用 $(...)* 符號,而 ... 可以是一個 expr 或是一個 pat,或其他標示符號也可以
我們可以看到下方的 () 第二個參數為 * 這表示他會重複 $() 裡面的參數
fn main() {
    macro_rules! introduction {
        ($($message:expr), *) => {
            $(
                println!("My name is {}!", $message);
            )*
        };
    }
    introduction!("Ning", "Jane", "Amy");
}
當我們編譯完並執行時,傳了三次參數進去,他就會跑三次結果出來
> cargo run
My name is Ning!
My name is Jane!
My name is Amy!