Macros
Macro Repetition
Macro repetition ($( ... )sep*, +, or ?) allows a macro_rules! pattern to match zero, one, or arbitrarily many occurrences of a token pattern and expand them in lock-step inside the transcriber.
Repetition Operators and Syntax
$( pattern_to_repeat ) separator quantifier
^^ ^^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^ ^^^^^^^^^^
│ body │ optional *, +, or ?
└── repetition group ──┘ (, ; =>)
| Quantifier | Meaning | Separator Allowed? | Example Matcher |
|---|---|---|---|
* |
Zero or more repetitions ($0, 1, 2, \dots$) | Yes (e.g., , or ;) |
$($x:expr),* |
+ |
One or more repetitions ($1, 2, 3, \dots$) | Yes (e.g., , or ;) |
$($x:expr),+ |
? |
Zero or one repetition (optional, $0$ or $1$) | No | $(,)? (optional trailing comma) |
Supporting Optional Trailing Commas ($(,)?)
In ($($x:expr),*), the separator , is matched between elements, so my_vec![1, 2,] with a trailing comma fails unless you append $(,)? after the repetition group:
macro_rules! hash_map {
// Empty map:
() => {
std::collections::HashMap::new()
};
// One or more `key => value` pairs with optional trailing comma `$(,)?`:
( $( $key:expr => $val:expr ),+ $(,)? ) => {{
let mut map = std::collections::HashMap::new();
$(
map.insert($key, $val);
)+
map
}};
}
fn main() {
let codes = hash_map! {
"OK" => 200,
"Not Found" => 404, // Trailing comma accepted via `$(,)?`
};
println!("OK = {}, Not Found = {}", codes["OK"], codes["Not Found"]);
}
OK = 200, Not Found = 404
Lock-Step Expansion of Multiple Repeated Variables
When a matcher captures two or more repeated metavariables ($k and $v) at the same repetition depth, you can expand them together inside the same $( ... )* loop or separately in different $( ... )* loops:
macro_rules! zip_tuples {
( [ $($a:expr),* ] , [ $($b:expr),* ] ) => {
vec![ $( ($a, $b) ),* ]
};
}
fn main() {
let paired = zip_tuples!([1, 2, 3], ["one", "two", "three"]);
println!("Paired: {paired:?}");
}
Paired: [(1, "one"), (2, "two"), (3, "three")]
(If the two lists passed to zip_tuples! have different lengths, the compiler emits a compile-time error: meta-variable 'a' repeats 3 times, but 'b' repeats 2 times.)