2015-12-19 32 views
2

我目前正在研究Rust宏,我無法找到有關重複的任何詳細文檔。我想用可選參數創建宏。這將是我的想法:如何使用重複創建具有可選參數的Rust宏?

macro_rules! single_opt { 
    ($mand_1, $mand_2, $($opt:expr)*) =>{ 
     match $opt { 
      Some(x) => println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, x); 
      None => single_opt!($mand_1, $mand_2, "Default"); 
     } 
    } 
} 

fn main() { 
    single_opt!(4,4); 
} 

這似乎已經過時了,因爲我不能編譯。 Rust書很簡短地提到這個話題。我如何得到這個例子的工作?

回答

6

鏽病本書有rather long chapter on macros,但重複的部分是例子有點害羞...

有幾種方法來處理宏可選參數。如果你有一個只能出現一次的可選參數,那麼你不應該使用重複:你應該不是在你的宏定義多種模式,如:

macro_rules! single_opt { 
    ($mand_1:expr, $mand_2:expr) => { 
     single_opt!($mand_1, $mand_2, "Default") 
    }; 
    ($mand_1:expr, $mand_2:expr, $opt:expr) => { 
     println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, $opt) 
    }; 
} 

fn main() { 
    single_opt!(4, 4); 
} 

如果你想允許的參數任意數量,那麼你需要重複。您的原始宏不起作用,因爲您將逗號放在重複之外,所以您必須調用該宏作爲single_opt!(4,4,);

如果你的論點,然後重複一個固定的數字,你可以把逗號重複內的第一個標記:

macro_rules! single_opt { 
    ($mand_1:expr, $mand_2:expr $(, $opt:expr)*) => { 
     println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, $($opt),*) 
    }; 
} 

但是,它並沒有在這種特殊情況下的工作:

<anon>:2:33: 2:47 error: `$mand_2:expr` is followed by a sequence repetition, which is not allowed for `expr` fragments 
<anon>:2  ($mand_1:expr, $mand_2:expr $(, $opt:expr)*) => { 
             ^~~~~~~~~~~~~~ 

所以我們得回去定義兩種模式:

macro_rules! single_opt { 
    ($mand_1:expr, $mand_2:expr) => { 
     single_opt!($mand_1, $mand_2, "Default") 
    }; 
    ($mand_1:expr, $mand_2:expr, $($opt:expr),*) => { 
     { 
      println!("1. {} 2. {}", $mand_1, $mand_2); 
      $(
       println!("opt. {}", $opt); 
      )* 
     } 
    }; 
} 

fn main() { 
    single_opt!(4, 4, 1, 2); 
} 

一重複的形式爲$(PATTERN) SEPARATOR COUNT,其中PATTERN是要重複的模式,SEPARATOR是分隔每次重複一個可選的令牌(在這裏,它是,)和COUNT是「零個或多個」要麼*+爲「一個或多個發生」。

然後,在宏擴展中,我們需要一個重複塊才能訪問$opt。語法完全相同,但請注意分隔符不必相同(這裏,擴展中沒有分隔符)。

相關問題