The everyday way to write a macro is macro_rules! — a declarative macro that works by pattern matching on syntax, much like match works on values.
Pattern-matching on tokens
macro_rules! defines rules: each is a pattern of tokens and the code to generate when input matches. The patterns use metavariables like $x:expr (match an expression), $n:ident (an identifier), $t:ty (a type). When you invoke the macro, the compiler matches your input against the rules and expands the matching one.
Repetition
The real power is repetition: $( $x:expr ),* matches a comma-separated list of expressions, and you expand over them with $( ... )* in the output. That's how a macro accepts any number of arguments — it's literally how vec! is built. One pattern handles zero, one, or a hundred elements.
$x:expr captures an expression you can paste into the output; $( ... ),* captures and repeats a comma-separated list. Once you see that macro_rules! is just match-on-syntax with repetition, the alien syntax becomes readable.When to write one
A declarative macro is the right tool for reducing boilerplate that varies by syntax, not just by value — building a collection with custom syntax, generating repetitive trait impls, a small DSL. If you find yourself copy-pasting code that differs only in a token, a macro might be the cure — after you've ruled out a function or generic.