A macro transcriber is the output side of a Rust declarative macro rule. A rule pairs a matcher with a delimited transcriber: when an invocation matches, the transcriber’s code is generated at the invocation site. section 2.0 section 2.5
In `macro_rules!`, write rules as `(matcher) => (transcriber)`. Both sides require delimiters—parentheses, braces, or square brackets—and multiple rules are separated with semicolons. Parentheses are a practical default, while braces can obscure nested code blocks. section 2.1.1
Generating an empty vector
An empty matcher can select a transcriber containing `Vec::new()`. Calling `my_vec!()` is replaced with `Vec::new()`, while the surrounding statement, including its semicolon, remains in place. A literal matcher such as `(make an empty vec)` can generate the same output. section 2.1.3 section 2.1.4
A transcriber can reuse values captured by its matcher. For `{$x:expr}`, `$x` is inserted into generated code that creates a vector and pushes the supplied expression. Repetition can similarly emit one `push` call per matched expression. Prefer concrete fragment specifiers such as `expr` before using broad `tt` matches, and test broad matches carefully. section 2.1.4
Listing 2.1 my_vec, our first declarative macro
macro_rules! my_vec { #1
() => [ #2
Vec::new()
]; #3
(make an empty vec) => ( #4
Vec::new()
); #5
{$x:expr} => {
{
let mut v = Vec::new();
v.push($x);
v
}
}; #6
[$($x:expr),+] => (
{
let mut v = Vec::new();
$(
v.push($x);
)+
v
}
)
}
fn main() {
let empty: Vec<i32> = my_vec![];
println!("{:?}", empty); #7
let also_empty: Vec<i32> = my_vec!(make an empty vec);
println!("{:?}", also_empty);
let three_numbers = my_vec!(1, 2, 3);
println!("{:?}", three_numbers); #8
}
Inspect a complete `my_vec!` macro with empty, literal, single-expression, and repeated-expression matchers, each paired with generated vector-building code. section 2.1
Transcribers make declarative macros useful for removing boilerplate, expressing default arguments or varargs, and building DSL-like syntax. Captured input, recursive macro calls, and macro hygiene support larger generated-code patterns; procedural macros remain an option when declarative rules are insufficient. section 2.5
