cosj
August 20, 2022, 7:12pm
1
Situation:
An enum with over 50 variants.
Each variant implements its own variation of the show
function
An array of enum is created
Enum implements a show function that dispatches (statically) to the variants show
function
Is there a way to avoid having to type the match with the 50 variants?
playground
You could implement Display
on your VariantA
, etc, and then use derive_more::Display
to implement it for the enum
.
Having Display
gets you ToString
, and to_string()
has the same signature as your show
. You could then rewrite your show
s to be something like
fn show(&self) -> String {
let s = self.to_string();
println!("show: {s}");
s
}
And you could even make this your own trait so you only write it once:
pub trait Show: ToString {
fn show(&self) -> String { /* as above */ }
}
impl<T: ToString + ?Sized> Show for T {}
Playground, except derive_more
isn't available there.
3 Likes
If you don't want to be constrained by the traits derive_more forwards, this would be an ideal problem to solve with your own derive macro. To learn about proc macros I recommend the proc macro workshop by dtolnay.
If you don't mind a little boilerplate you could also use a declarative macro like described here: rust - Calling common method on enum types - Stack Overflow
Btw: it should be relatively straight forward to solve this for the general case of forwarding some function call to all enum variants. You could for example have an attribute like
#[forward(show(&self))]
Does anyone know whether this already exists?
2 Likes
For instance:
macro_rules! impl_various {
($($var:ident),*) => {
enum Various { $(
$var($var),
)*}
impl Various {
fn show(&self) -> String {
match &self {
$(Various::$var(variant) => variant.show(),)*
}
}
}
}
}
impl_various!{ VariantA, VariantB }
2 Likes
ambassador
can I think, but I haven't played with it.
1 Like
I've written one such crate: https://crates.io/crates/impl-enum
#[impl_enum::with_methods {
fn show(&self) -> String
}]
enum Various {
VariantA(VariantA),
VariantB(VariantB),
// ....
}
It's similar to ambassador's delegatable_trait_remote
but doesn't involve traits which could be a good or bad thing depending on what you're doing.
1 Like
cosj
August 23, 2022, 6:09pm
7
Thanks to all for the suggestions.
I'll need some time to process all of it
system
Closed
November 21, 2022, 6:10pm
8
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.