CodeBlanks Logo Icon CodeBlanks

Summary - Declarative macros

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

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
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

Question
($($x:expr),+ ____) => {{
    let mut v = Vec::new();
    $(v.push($x);)+
    v
}};
Answer
($($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

All lessons in Advanced