- Rust Programming By Example
- Guillaume Gomez Antoni Boucher
- 445字
- 2021-07-02 19:13:01
Repetitions
In a macro pattern, it is also possible to match against an unlimited number of patterns, using the repetition operators + and *. They behave exactly like the same operators in regular expressions:
- + matches 1 or more times.
- * matches 0, 1, or more times.
Let's write a very useful macro, a macro to provide syntactic sugar to create HashMaps:
Note: A HashMap is a data structure from Rust's standard library that maps keys to values.
macro_rules! hash { ($( $key:expr => $value:expr ),*) => {{ let mut hashmap = ::std::collections::HashMap::new(); $(hashmap.insert($key, $value);)* hashmap }}; }
As we can see, we use the * operator here. The comma before it specify the separator token: this token must be present between each occurrence of the pattern between parentheses (which is the pattern that can be repeated). Don't forget the leading $ before the opening parenthesis; without it, the macro will match the literal (. Inside the parentheses, we see a normal pattern, an expression, followed by the => operator, followed by another expression. The body of this rule is particular, since it uses two pairs of curly brackets instead of only one.
First, let's look at how we use this macro, and we'll go back to this peculiarity right after:
let hashmap = hash! { "one" => 1, "two" => 2 };
If we were to use only one pair of curly brackets, like this:
macro_rules! hash { ($( $key:expr => $value:expr ),*) => { let mut hashmap = ::std::collections::HashMap::new(); $(hashmap.insert($key, $value);)* hashmap }; }
The compiler will try to generate the following code, which doesn't compile:
let hashmap = let mut hashmap = ::std::collections::HashMap::new(); hashmap.insert("one", 1); hashmap.insert("two", 2); hashmap;
It doesn't compile because Rust wants an expression on the right-hand side of =. To transform this code into an expression, we simply need to add the curly brackets:
let hashmap = { let mut hashmap = ::std::collections::HashMap::new(); hashmap.insert("one", 1); hashmap.insert("two", 2); hashmap };
Hence the second pair of curly brackets.
There's one remaining line that requires an explanation in the body of the macro:
$(hashmap.insert($key, $value);)*
This means that the statement will be repeated as many times as there are pairs of key/values. Notice that ; is inside the parentheses; and there's no separator before * because every statement needs to end with a semicolon. But it's still possible to specify a separator here, as shown in the following example:
let keys = [$($key),*];
This will expand all the $keys, separating them by a comma. For instance, with a call like:
hash! { "one" => 1, "two" => 2 }
It will results in:
let keys = ["one", "two"];
- 蒲城文獻(xiàn)征錄
- 中國古代圖書館學(xué)研究
- 檔案保護技術(shù)
- 博物館與文化浙江建設(shè):浙江省博物館學(xué)會2017年學(xué)術(shù)研討會論文集
- 升維閱讀
- 大學(xué)圖書館信息服務(wù)與信息素養(yǎng)教育理論與實踐研究
- 基于價值全面實現(xiàn)的檔案信息資源配置
- 檔案與少數(shù)民族記憶
- 梁思成林徽因影像與手稿珍集
- 金開誠文選
- 李一氓文存(第三卷):題跋·詩聯(lián)·劇本
- 圖書館服務(wù)均等化與資源共享(下冊)
- 圖書館學(xué)研究法:學(xué)術(shù)論文寫作摭要
- 電子文件長期保存:理論與實踐
- 文化與詩學(xué)(2009年第1輯)(總第8輯)