TLDR
Is it possible to nest invocations of macro_rules!
macros, using the inner one to generate arguments passed to the outer one?
In other words, can some variation on the following line ever compile?
outer!(inner!(arg))
Put another way, does something akin to quasiquotation / unquoting exist in Rust macros?
Specific example
How would you formulate test use_generated
below?
// A macro that uses two inputs
#[macro_export]
macro_rules! use {
($name:ident $operator:tt) => {
format!("{} {}", stringify!($name), stringify!($operator))
}
}
// Verify what the `use` macro received
#[test]
fn use_hand_given() {
assert_eq!(use!(Add +=), "Add +=");
}
// A macro that generates different sets of symbols depending on input
#[macro_export]
macro_rules! generate {
(+) => (Add +=);
(-) => (Sub -=);
(*) => (Mul *=);
// etc.
}
// Try to use the generated symbols as arguments to `use!`
#[test]
fn use_generated() {
assert_eq!(use!(generate!(+)), "Add +=");
}
Background
In the context of implementing arithmetic operators
I am exploring designs of macros which write all the required trait implementations.
Implementing a full set of arithmetic operators for a single operation requires use of six symbols:
- For
+
:+
,+=
,Add
,AddAssign
,add
andadd_assign
- For
*
:*
,*=
,Mul
,MulAssign
,mul
andmul_assign
- ... and so on
I can write a macro with an interface approximately like this
make_ops(+ += Add AddAssign add add_assign for MyType (self, other) {
...
})
but burdening the user with having to write out the six symbols each time is naff. I would like the interface to be something like
make_ops(+ for MyType (self, other) {
...
})
The idea is to generate the remaining 5 symbols using a macro like generate!
above.
Can this ever work?
Is there some better solution?
paste
-based solution
The macro could use add
and add_assign
instead of +
and +=
in its implementation, so using the paste
crate I see how to implement an interface like
make_ops(add for MyType (self, other) {
...
})
which could be a viable solution to this specific problem, but I'd be interested to learn what is possible more generally.