Here\'s a synthetic example of what I want:
macro_rules! define_enum {
($Name:ident { $($Variant:ident),* }) => {
pub enum $Name {
You can handle both cases by... handling both cases:
macro_rules! define_enum {
($Name:ident { $($Variant:ident,)* }) => {
pub enum $Name {
None,
$($Variant),*,
}
};
($Name:ident { $($Variant:ident),* }) => {
define_enum!($Name { $($Variant,)* });
};
}
define_enum!(Foo1 { A, B });
define_enum!(Foo2 { A, B, });
fn main() {}
We've moved the main implementation to the version that expects the trailing comma. We then added a second clause that matches the case with the missing comma and rewrites it to the version with a comma.
DK. points out an alternative, making the trailing comma itself optional:
($Name:ident { $($Variant:ident),* $(,)* }) => {
// ^^^^^
This avoids the need to delegate from one implementation to the other.
In Rust 2018, starting with Rust 1.32, you can use the ?
macro repeater to write this in a more obvious manner and disallow multiple trailing commas:
($Name:ident { $($Variant:ident),* $(,)? }) => {
// ^^^^^
Change the line
($Name:ident { $($Variant:ident),* }) => {
to
($Name:ident { $($Variant:ident),* $(,)? }) => {
to add an optional comma at the end. This works in stable Rust / 2018 edition. This syntax also works for other separators like a semicolon.