ProgramGuru

Macros and repeated syntax

Macros and repeated syntax

Printing has used println! throughout the course. A macro expands input syntax into Rust code during compilation. A function receives runtime values through a defined type signature. Macros can accept flexible syntax, but a function is often easier to inspect for an ordinary calculation.

What you’ll learn

  • Explain why println! expands syntax during compilation.
  • Choose a function when runtime value processing is sufficient.

Macros and repeated syntax in action

  1. Match invocation syntax

    The invocation matches the two-expression pattern.

    Match invocation syntax
  2. Expand into println!

    Its expansion is a println! call with the name and mark arguments.

    Expand into println!
  3. Run the checked print

    The generated code is then type-checked; being a macro does not remove Rust’s language checks.

    Run the checked print
The invocation matches the two-expression pattern. Its expansion is a println! call with the name and mark arguments. The generated code is then type-checked; being a macro does not remove Rust’s language checks.

Macros and repeated syntax explained

macro_rules! defines a declarative macro. A pattern such as $name:expr accepts an expression, and the expansion inserts it into generated code. This example uses each supplied expression once. Macros can accidentally evaluate an expression multiple times if their expansion repeats it.

Work through the Rust program

Save the complete source as main.rs in the Rust environment. No standard input is needed.

Rust 2024 · complete program

macro_rules! report_line {
  ($name:expr, $score:expr) => { println!("{}: {}", $name, $score); };
}
fn main() { report_line!("Diya", 80); }

Expected output

Diya: 80

Follow the execution

The invocation matches the two-expression pattern. Its expansion is a println! call with the name and mark arguments. The generated code is then type-checked; being a macro does not remove Rust’s language checks.

Try the complete program in the Rust compiler. For tests, Cargo commands and local files, use the specified local environment.

Try a small variation

Your task: Does a macro invocation execute arbitrary untyped code after the program starts?

Rust 2024 · complete program

macro_rules! report_line {
  ($name:expr, $score:expr) => { println!("{}: {}", $name, $score); };
}
fn main() { report_line!("Diya", 80); }

Worked answer

No. This declarative macro expands syntax during compilation, and the generated Rust code is checked. Its resulting print operation runs later in the executable.

Mistakes and limits to recognize

Procedural macros operate through a different mechanism and can have build-time responsibilities. Prefer a function for a simple reusable bonus calculation. Avoid hiding side effects or resource access inside surprising macro expansions.

Check your understanding

Does a macro invocation execute arbitrary untyped code after the program starts?
Choose one answer. You can try again.

Answer and explanation

No.

No. This declarative macro expands syntax during compilation, and the generated Rust code is checked. Its resulting print operation runs later in the executable.

Take the idea into your next program

No. This declarative macro expands syntax during compilation, and the generated Rust code is checked. Its resulting print operation runs later in the executable. Procedural macros operate through a different mechanism and can have build-time responsibilities.

Further reading: the official Rust Book on macros and repeated syntax.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Unsafe code and external boundaries →