Is there a way to access variables defined in rust macros from a passed expr?

Assuming I want to make the following macro work:

macro_rules! process_numbers {
    ($name:ident, $process:expr) => {
        let $name: Vec<_> = vec![0, 1, 2].iter().map(|num| {
            println!("{}", path); // dummy preprocessing
            let foo = 3; // some other preprocessing involving side-effects
            $process
        }).collect();
    }
}

process_numbers!(name, {
    num + foo
});

Is there a way so that I could access num and foo from within $process?

1 answer

  • answered 2022-01-13 05:01 Francis Gagné

    Rust macros are hygienic. This means that identifiers defined within a macro's body won't leak out of it.

    One way to solve this is to modify the macro such that it receives the identifiers as parameters.

    macro_rules! process_numbers {
        ($name:ident, |$num:ident, $foo: ident| $process:expr) => {
            let $name: Vec<_> = vec![0, 1, 2].iter().map(|$num| {
                println!("{}", path); // dummy preprocessing
                let $foo = 3; // some other preprocessing involving side-effects
                $process
            }).collect();
        }
    }
    
    process_numbers!(name, |num, foo| {
        num + foo
    });
    

    Here, I'm using syntax that looks like a closure, which suggests that |num, foo| declare parameters (they actually declare variables – close enough!).

    Another way would be to make the $process argument a literal closure (or any invokable expression) that the macro would invoke, passing num and foo as arguments.

    macro_rules! process_numbers {
        ($name:ident, $process:expr) => {
            let $name: Vec<_> = vec![0, 1, 2].iter().map(|num| {
                println!("{}", path); // dummy preprocessing
                let foo = 3; // some other preprocessing involving side-effects
                $process(num, foo)
            }).collect();
        }
    }
    
    process_numbers!(name, |num, foo| {
        num + foo
    });
    

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum