Your issue isn't with name!()
, but with call_init!()
. The call_init!()
macro is defined to accept a string literal as its first argument but you've actually passed it the tokens name
, !
, (
, "set1"
, ,
, "set2"
, and )
. That's because macros are evaluated from the outside-in and not the inside-out like expressions.
Something you might try is the callback pattern. This is where you define a macro which takes the name of a macro to invoke and its arguments.
Here's a simple example:
macro_rules! call_it {
($macro_name:ident, $($args:tt)*) => {
$macro_name!( $($args)* )
}
}
fn main() {
call_it!(println, "Hello, {}", "world");
}
(playground)
In your case you want to combine the callback pattern with some form of iteration, either the normal $(...)*
or recursion.
For my implementation I'm just using a call_init!()
that prints out any arguments you gave it.
macro_rules! call_init {
($($token:tt)*) => {
println!(concat!(
"Called with {{ ",
$( stringify!($token), " " ),*,
"}}"
));
}
}
This is my version of name!()
.
macro_rules! name {
(
// the name of the macro we are going to invoke
$macro_name:ident,
// We'll invoke the macro once for each of these arguments
[
// Peel off the first one
$first_variable_arg:literal
// And save the rest to the $variable_args sequence
$(, $variable_args:tt),*
],
// Stash away the arguments we are going to use every time
[$($fixed_args:tt),*]
) => {
// Invoke the macro using our first variable argument
$macro_name!($first_variable_arg, [$($fixed_args),*]);
// then recurse so we can handle the other variable arguments
name!($macro_name, [$($variable_args),*], [$($fixed_args),*]);
};
// Do nothing because there are no more variable arguments
($macro_name:ident, [], [$($fixed_args:tt),*]) => {};
}
And here is how it is used:
fn main() {
// call_init!("set1", [f1, f2]);
// call_init!("set2", [f1, f2]);
name!(call_init, ["set1", "set2"], [f1, f2]);
}
(playground)