Summary - Declarative macros
- Rust course
- Advanced
- Lesson 47/81
- 5 min
Combine macro_rules! and repetitions to build a vec_of! macro.
Declarative macros summary
macro_rules! generates code through pattern matching. Fragments (expr, ident, ty, tt...) say what is expected, repetitions ($(..),*, +, ?) how many times. Several arms and recursion are possible. Macros are hygienic; when exported, #[macro_export] and $crate:: are used. If a function is enough, write a function; macros are for variadic arguments, code generation and compile-time checks.
Your own vec! macro
A list macro supporting empty use, repetition and a trailing comma:
macro_rules! liste {
() => {
Vec::new()
};
($($x:expr),+ $(,)?) => {{
let mut v = Vec::new();
$(v.push($x);)+
v
}};
}The real vec! computes the element count at compile time to preallocate capacity.
Practice List macro
Write the liste! macro above. Print let a: Vec<i32> = liste![]; and, with a trailing comma, let b = liste![1, 2, 3,]; with {:?}, separated by a space.
Starter code
fn main() {
// buraya yaz
}Sample solution
macro_rules! liste {
() => {
Vec::new()
};
($($x:expr),+ $(,)?) => {{
let mut v = Vec::new();
$(v.push($x);)+
v
}};
}
fn main() {
let a: Vec<i32> = liste![];
let b = liste![1, 2, 3,];
println!("{:?} {:?}", a, b);
}Expected output
[] [1, 2, 3]
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 How do <code>vec![0; 5]</code> and <code>vec![1, 2]</code> work with the same macro?
- Both are the same pattern
- It doesn't work
- vec! has two separate arms: ($e:expr; $n:expr) and ($($x:expr),*) Correct answer
- The compiler treats it specially
Explanation: Macro arms are tried in order; the semicolon doesn't fit the second arm's pattern.
2 Trailing comma
($($x:expr),+ ____) => {{
let mut v = Vec::new();
$(v.push($x);)+
v
}};
($($x:expr),+ $(,)?) => {{
let mut v = Vec::new();
$(v.push($x);)+
v
}};
Explanation: $(,)? accepts an optional single comma.
3 Group summary
| Term | Meaning |
|---|---|
macro_rules! |
Generates code by pattern |
$x:expr |
Fragment |
$(..),* |
Repetition |
Hijyen |
No name clashes |