Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a macro containing multiple items into a macro?

Tags:

Given this simple macro that expands multiple items, how could this take a macro as an argument?

macro_rules! print_structs {
    ($($t:ty)*) => ($(
        println!("{:?}", TypeId::of::<$t>());
    )*)
}

// expands one println per type!
print_structs! { i8 i16 usize String }

How could a pre-defined macro of types be passed in?

Example of non-working macro:

macro_rules! some_types {
    () => {
        i8 i16 usize String
    }
}

print_structs! { some_types!() }

See play.rust-lang.org example, uncomment UNCOMMENT TO TEST lines to see the problem.

Gives the error: macro expansion ignores token `i16` and any following


I also tried to put the list in a file to include, eg:

print_structs! {
    include!("some_types.in")
}

... however this gives an error: expected type, found `include!("../struct_list.rs")`

like image 403
ideasman42 Avatar asked Feb 08 '17 07:02

ideasman42


People also ask

How do I pass a variable from one macro to another?

To do that, you create what are called arguments. You come up with a name for a variable that you can use in the macro and put it in the middle of the parentheses at the top of the macro. This argument can then be used within the macro as a regular variable.

How do I pass a parameter to a macro in Excel?

To assign a macro that you pass arguments to a button, shape, image, or any object, you first right-click that object and click Assign Macro and then type the name of the macro and the argument, following the pattern described in the above examples, and then click OK.

Can a macro call itself?

A recursive macro is one that calls itself over and over to perform a specific task.

What is parameters in macro?

Macro parameter values are character sequences of no formal type, and they are comma delimited. There is no way to pass in a comma as part of a parameter value. The number of parameters passed can be less than, greater than, or equal to the number of parameters that the macro value is designed to receive.


1 Answers

From looking into this, it seems that its not possible to expand a list inside a macro using a macro or include.

Although code-generation is an option, its quite involved so will leave it out of this answer.

It is possible to get similar functionality by swapping macro use around, instead of passing the list into a macro, pass a macro name into a generic macro that expand it with a list.

Heres a working example:

macro_rules! print_structs {
    ($($t:ty)*) => ($(
        println!("{:?}", ::std::any::TypeId::of::<$t>());
    )*)
}

macro_rules! apply_macro_to_structs {
    ($macro_id:ident) => {
        $macro_id! {
            i8 i16 usize String
        }
    }
}

fn test_a() {
    // expands one println per type!
    print_structs! { i8 i16 usize String }
}

fn test_b() {
    // expand using a macro
    apply_macro_to_structs!(print_structs);

}

fn main() {
    test_a();
    test_b();
}
like image 106
ideasman42 Avatar answered Sep 21 '22 11:09

ideasman42