I'm attempting to condense some repetitive code that has structure similar to:
match self.foo() {
None => self.bar(),
Some(MyStruct { foo: x, .. }) => match x {
Pattern1 => result,
Pattern2 => {
block_result
}
}
}
which I would like to write as something like:
my_macro!(
Pattern1 => result,
Pattern2 => {
block_result
}
)
avoiding the repetitive None
handling and MyStruct
destructuring.
This seems like it should be pretty simple, as it's essentially just substituting the macro body into a match expression, but I can't actually see any way to do this.
I attempted to write the macro as follows:
macro_rules! my_macro (
($($pat:pat => $result:expr,)*) => (
match self.foo() {
None => self.bar(),
Some(MyStruct { foo: x, .. }) => match x {
$(
$pat => $result,
)*
},
}
);
)
but this fails, as the RHS of a match arm can be an expression or a block (and it also doesn't deal with optionally omitting the comma for the last arm). As far as I'm aware there's no way to specify that part of a macro pattern can be a block or an expression, so I can't think of a way to resolve this.
Ideally I'd like to do this without having to write complicated patterns that destructure match bodies only to stick them back together again, but I don't think there's any designator that will accept the body of a match expression.
How would you go about writing this macro? Is it even possible without writing a compiler plugin?