Codecademy Logo

Macros

macro_rules!

Declarative macros allow us to take syntactic fragments of the Rust language as input and then return raw source code. A bonus of declarative macros is that they allow arbitrary repetition of code.

macro_rules! make_it {
() => {
// Everything placed here will be generated in source code when the macro is called.
}
}

Input

When working with macros, parameters are referred to as Metavariables, and their respective types are called fragment-specifiers.

We can declare our metavariables in a similar manner as function parameters. However, metavariables must start with $, and there can be no spaces between the metavariable, its fragment-specifier, and the separating :.

macro_rules! make_it {
($happen:expr) => {
println!("{}", $happen)
}
}
make_it!("we did it!");
make_it!(usize::MAX);
// Here we have let our macro accept any expression which we can represent with the metavariable `$happen` and passing it to `println!()`.

Repetition

Macros make it easy to repeat fragments of code. We can repeat code by enclosing it within $() followed by either a *, +, or ?.

  • * will accept any number of repetitions, including none.
  • + will accept any number of repetitions but requires at least one.
  • ? will accept one or no repetitions.

By adding the , to create $(),+ in our input, we are stating that the repeated items are delimited by ,. We can use any single token as a delimiter that is valid in the context of nearby metavariables.

macro_rules! make_it {
( $var:ident => $($count:expr),+) => {
$($var.push($count);)+
}
}
let mut count = vec![];
make_it![count => u8::MIN, 1, 2];
println!("{count:?}");

Exporting

Macros can be exported and used anywhere in our crate with the #[macro_export] attribute. This also makes the macro visible to other crates when importing our crate as a dependency.

#[macro_export]
macro_rules! make_it {
( $var:ident => $($count:expr),+) => {
$($var.push($count);)+
}
}
// Alternatively, we can also export all macros contained within a module with the #[macro_use] attribute
#[macro_use]
mod macros;

Learn More on Codecademy