rustrust-macros

Extract objects in an expression in a macro in Rust


I have tried to pass my local objects in a macro call with a spesific pattern and failed. For example:

macro_rules! run_map {
    (($vector: expr).map(($closure: expr))) => {
        $vector().iter().map($closure: expr).collect::<Vec<_>>()
    };
}

fn main() {
    let my_vector: Vec<i32> = vec![3,4,5];
    run_map!(my_vector.map(|e| e * e));
}

Here is the error i get:

run_map!(my_vector.map(|e| e * e));
         ^^^^^^^^^ no rules expected this token in macro call

How can i extract objects and use them separately in an expression in a macro?


Solution

  • Expressions in macros must be delimited in some way.

    macro_rules! run_map {
        (($vector: expr).map($closure: expr)) => {
            // remove the () after $vector and the :expr after $closure here
            $vector.iter().map($closure).collect::<Vec<_>>()
        };
    }
    
    fn main() {
        let my_vector: Vec<i32> = vec![3,4,5];
        // add () around my_vector and the closure here
        let out = run_map!((my_vector).map(|e| e * e));
        println!("{out:?}");
    }
    

    See demo in the rust playground

    The macro needs to be able to determine which part of the expression you want and which you don't. So it must be surrounded by something not valid in an expression like {}, () or []. Even something like:

    ($vector: expr;.map(($closure: expr))) => {
    

    Works because a ; is a valid delimiter for expressions