Weekly Rust Trivia is a problem-oriented series of articles that assist developers while learning Rust. Every article solves simple, everyday development tasks using the Rust standard library or leveraging popular and proven crates.

Question: How to implement a function-like macro in Rust?

Function-like macros in Rust are powerful tools that allow you to define macros that resemble function calls. They can take in arguments and generate code based on those arguments. Function-like macros are defined using the macro_rules! keyword and a set of rules that define patterns and transformations. For demonstration purposes, we’ll define the factorial macro, which will generate code to calculate the factorial of a given number:

macro_rules! factorial {
    ($num:expr) => {
        {
            let mut result = 1;
            let mut n = $num;

            while n > 0 {
                result *= n;
                n -= 1;
            }

            result
        }
    };
}

The generated code initializes a mutable variable result to 1 and assigns the value of the captured expression to a mutable variable n. It then enters a while loop, where it multiplies result with n and decrements n by 1 in each iteration. This process continues until n becomes 0. Finally, the calculated factorial value is returned as the result of the macro.

In Rust, we can use a function-like macro by invoking its name followed by an exclamation mark (!). Inside the parentheses, you provide the necessary arguments or expressions based on the macro’s defined pattern. The macro expands and generates code, which is then used in your program.

fn main() {
    let number = 5;
    let factorial = factorial!(number);
    println!("Factorial of {} is: {}", number, factorial);
}