官术网_书友最值得收藏!

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"];
主站蜘蛛池模板: 景宁| 秭归县| 湖州市| 利川市| 新安县| 巢湖市| 赤城县| 云安县| 双鸭山市| 南投市| 凤阳县| 崇州市| 封开县| 赤峰市| 吉安县| 西安市| 大同市| 淮北市| 汝阳县| 沾益县| 丰台区| 韶关市| 始兴县| 肥城市| 荥阳市| 泗阳县| 汤原县| 龙口市| 德化县| 白水县| 恩平市| 肥城市| 双鸭山市| 铜山县| 公主岭市| 安福县| 龙江县| 沙湾县| 大港区| 西藏| 阿合奇县|