DRY enum struct-like variants


#1

I have encountered the want several times recently where in an enum with only struct-like variants all but a few fields are shared both in name and in type between the variants.

Example:

pub enum Foo {
    Var1 {
        wealth: i32,
        likeable: bool,
        age: i16
    },
    Var2 {
        wealth: i32,
        likeable: bool
    }
}

It would be vary nice, both from a readability standpoint and a DRY standpoint if it were possible to do the following (or something like it):

pub enum Foo {
    Var1 {
        likeable: bool
    },
    Var2,
    { // blank block 
        wealth: i32,
        likeable: bool
    }
}

The two examples would have the same fields. As for errors this would not be allowed if some of the variants were tuple-like. As for implementation, I am not that well versed in how it is handled currently but to make it the most similar in each case I would say that the best place to put them is that the top of every variant.


#2

Or, to make it even more versatile the fields are just not added to tuple-like variants


#3

Currently, this is usually done via a inner: FooInner field with the wealth and likeable fields.

Bonus points for functionality: if the “global” members are accessible without matching the variant out.

[[ Side note: I don’t see struct-like variants much; I mostly see (primarily) all-newtype-variants or (sometimes) all-tuple-variants. ]]


#4

Interesting maybe parsing (which is what I am doing) lends itself to using struct-like variants


#5

When I need this, I usually just “transpose” my type setup and put the enum in a struct, factoring the common fields out and into the struct. From what I can tell it’s completely equivalent.

I would also be very surprised to see enums, which are sum types, contain common fields — that would make them a product type (a product of the “global” fields and the sum of all the other fields in the individual variants). I don’t think it’s a good idea to conflate sum and product types; let’s just use both for their sole purpose.


#6

Syn, the most battle-tested sea-of-enums uses struct-newtype-variant everywhere. The key benefit of which is that the variant now has a type you can talk about.

Honestly, until we find a way for variants-as-types or types-as-variants, the newtype-variant seems broadly useful for things like this. (With macros for dryer code.)


#7

IIRC the variants-as-types RFC has been accepted.


#8

No, it’s still open though I think there is a future-compat lint in that protects against -> Enum::Variant ambiguity where Variant is also an associated type. Last comment on the RFC was in January.


#9

Ah, you are right… I think I got it mixed up with another, accepted one.