Suppose I have two sets. (a, b, c) and (p, q) I want to generate a vector like this using a macro.
let v = vec![(a,p), (a, q), (b, p), (b, q), (c, p), (c, q)];
So this is the macro I was writing. There may be other ways to write this, but I want to understand why this does not work. I want to use this for something more complicated. I have used this pattern in the past (not in the same context) and not sure why this does not work.
fn main() {
macro_rules! vec_gen {
([$($left_item:ident),*], $right:tt) => {
vec![$(vec_gen!(@call $right, $left_item)),*]
};
(@call ($($right_item:ident),*), $left_item:ident) => {
$(($left_item, $right_item),)*
};
}
let a = 1;
let b = 2;
let c = 3;
let p = 1;
let q = 2;
let r = 3;
let data = vec_gen!([a, b, c], (p, q, r));
println!("{:?}", data);
}
rust-analyzer macro expansion shows this: (Not exactly what I want - it has extra set of parenthesis - at least it gives some results).
// Recursive expansion of vec_gen! macro
// ======================================
(<[_]>::into_vec(
#[rustc_box]
$crate::boxed::Box::new([
((a, p), (a, q), (a, r)),
((b, p), (b, q), (b, r)),
((c, p), (c, q), (c, r)),
]),
))
Even though this generates some code in rust-analyzer macro expansion, it gives this error message when building.
error: macro expansion ignores token `,` and any following
--> src\main.rs:7:40
|
4 | vec![$(vec_gen!(@call $right, $left_item)),*]
| ----------------------------------- help: you might be missing a semicolon here: `;`
| |
| caused by the macro expansion here
...
7 | $(($left_item, $right_item),)*
| ^
|
= note: the usage of `vec_gen!` is likely invalid in expression context
Now if I removed the ',' and add a ';' whole thing breaks down and rust-analyzer does not produce any output.
Also I am trying to understand this: "note: the usage of vec_gen!
is likely invalid in expression context". Why?
How to get this macro pattern right?