Rust尋找挫敗感1.0之宏(上)

以前有基友說寫的不夠看,因此今天特地加餐說一下宏。以前的案例中有提到過可使用println!宏進行打印。今天咱們就簡單來講說有關宏的幾個方面:編程

  • 宏與函數的區別
  • 如何定義聲明式宏(元編程)

宏與函數的區別

宏其實就是咱們一般所謂的元編程,在rust中使用宏來擴展生成比咱們手寫更多的代碼。數組

你們應該知道元編程對於減小大量編寫和維護的代碼試很是有用的,但他又和函數有點區別,好比一個函數必需要聲明它的參數個數和類型。可是宏只接受一個可變參數,並且能夠在編譯器翻譯代碼以前展開。這樣就意味着咱們想要實現一個宏比定義函數更加複雜,也更難理解和維護。函數

同時在rust中宏定義沒法出如今模塊命名空間,並且必需要在調用以前定義或者將其導入,而函數則能夠在任意地方。翻譯

聲明式宏

咱們可使用macro_rules!來定義宏,這在Rust中使用的比較普遍。接下來咱們介紹一下vector,這是rust中的一種集合類型。和數組不同的是他存儲在堆上,並且長度是動態增加的。並且vector是std中用泛型實現的,數組是原生內建的類型。具體有關vector的咱們暫時不展開,咱們只須要了解到可使用vec!來生成一個給定值的vector。如:code

let v: Vec<i32> = vec![1, 2, 3];

而後咱們移步vec!的實現,這是簡化過的定義:編譯器

#[macro_export]
macro_rules! vec {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

首先咱們看到的是一個註解,這個說明了該宏是可用的。而後macro_rules!定義了名字vec後面跟上大括號。而後就是( $( $x:expr ),* ),這句也就是一個模式(pattern),若是模式匹配了後面的相關代碼就會執行。這和後面要說的match表達式的結構相似。而後,一對括號包含了所有模式。接下來是後跟一對括號的美圓符號( $ ),其經過替代代碼捕獲了符合括號內模式的值。$() 內則是 $x:expr ,其匹配 Rust 的任意表達式或給定 $x 名字的表達式。編譯

$() 以後的逗號說明一個逗號分隔符能夠有選擇的出現代碼以後,這段代碼與在 $() 中所捕獲的代碼相匹配。緊隨逗號以後的 說明該模式匹配零個或多個 以前的任何模式。泛型

因此當 vec![1, 2, 3]; 調用宏時,$x 模式與三個表達式 一、2 和 3 進行了三次匹配。擴展

就此打住,否則再講下去打字員也是一臉懵逼了。命名空間

自定義過程式宏

在rust中第二種形式的宏叫作過程式宏。接收rust代碼做爲輸入,而後在代碼上進行操做產生另一些代碼輸出。因爲篇幅較長並且打字員也須要補補課因此咱們下次再介紹。

小結

看到這裏,你們是否是回憶起了C語言中的宏,種個草慢慢去研究趴。

相關文章
相關標籤/搜索