Re: [IDEA] allow extending enum

From: Date: Thu, 30 Mar 2023 07:36:08 +0000
Subject: Re: [IDEA] allow extending enum
References: 1 2 3 4 5 6  Groups: php.internals 
Request: Send a blank email to internals+get-119784@lists.php.net to get a copy of this message
On Wed, 29 Mar 2023 at 18:40, Larry Garfield <larry@garfieldtech.com> wrote: > > On Wed, Mar 29, 2023, at 2:25 PM, Rokas Å leinius wrote: > > First, I'm pretty sure I agree now that enums should *not* be > > extend-ed as regular classes, there's a fundamental > > difference as > > you state - the extended enum is a fundamentally different THING as it > > can hold different values - when an enum's sole purpose is to hold one > > of the set of values. > > > > That is to say - for most implementations that's the desired case. > > > > I'll refer to the solution to the OP problem as ECS, Error Code System. > > > > For ECS, the most elegant, but also the only, solution I can come up > > with - is the kind of enum that you also suggest, a > > base-enum. > > abstract enum? > > > > Let me try again to describe the problem that I came here with that is > > unsolvable by union types: > > > > 1. ECS is a *generic* component. I want to plug it into any working > > system (like an existing cms). > > 2. Invoking it must provide a unique ErrorCode. The existing cms has > > to create an enum that will be accepted as type: > > ErrorCode. It > > cannot edit the existing ErrorCode as it is part of ECS and not the > > cms. > > 3. There is NO special handling for the custom ErrorCode's that the > > users of ECS create. We are just using the enums inferred value. > > > > I will keep processing this situation further, but for now it seems to me like > > > > 1. Extending enums is fundamentally flawed. > > 2. Basing enums off of other enums has valid usage scenarios. > > > > In that case, and, again, this needs way more thought to it, it's not > > such a "generic way forward" that seemed to me at first and might only > > provide marginal value at the cost of type complexity and that is most > > probably, unfortunately, not worth it... > > > > (unless abstract enum might make sense, but my brain needs > > some time > > off of this problem for now) > > > > Thank you for such a thought out discussion, everyone! > > 1) Please don't top-post. > > 2) Some good reading material for this topic, both on enums and on error handling: > > https://peakd.com/hive-168588/@crell/on-the-use-of-enums > https://peakd.com/hive-168588/@crell/much-ado-about-null > > They're not short, but that's because they are complete. :-) > > 3) In the error code case, the answer is to leverage the fact that enums *do* support > interfaces. > > interface ErrorCode > { > public function message(): string; > } > > enum CommonErrors: string implements ErrorCode > { > case YourFault = 'You screwed up'; > case OurFault = 'We screwed up'; > > public function message(): string > { > return $this->value; > } > } > > readonly class SomeoneElseError implements ErrorCode > { > public function __construct(privateUser $atFault) {} > > public function message(): string > { > return sprintf('%s screwed up', $this->atFault->name()); > } > } > > Now an error handling system can type against the ErrorCode interface, common errors have > trivially simple enum values you can use, but you can also make your own. In this case, you're > *not* using an enum as a limited-set; you're taking advantage of it being a way to predefine > singleton objects. I would consider this a completely valid use of enums, and actually do something > very similar in my serialization library: > > úî™õþoσ¯ > ðÆÖhttps://github.com/Crell/Serde/blob/master/src/Renaming/RenamingStrategy.php > > https://github.com/Crell/Serde/blob/master/src/Renaming/Cases.php > > https://github.com/Crell/Serde/blob/master/src/Renaming/Prefix.php > > 4) As others have said, extending enums is a bad idea with lots of reasons it's a bad > idea, both conceptual and pragmatic. However, I would be open to discussing a > use for enums to import cases from one enum into another.. > > There's two concerns with that to consider: > > A) What happens to methods on the imported enum? Are they pulled in as well? Do interface > definitions carry over? I don't know. > > B) The long-term goal is to expand Enums to include associated values > (https://wiki.php.net/rfc/tagged_unions, although that's a bit out of date now so don't > take it as a roadmap). How would use-ing an enum within another > enum affect that? I have no idea, off hand. > > --Larry Garfield > 1) Please don't top-post. Am I doing it right now? I've never been on a mailing list. In fact, I was too young and missed out on BBS as well, and now using this laughably archaic collaboration method, receiving mostly stone-harsh replies generously sprinkled with genius insights, having to quite literally hack a registration form as one of the several required steps for contribution... Wow this is a really remarkable experience for me :D > 2) Some good reading material for this topic, both on enums and on error handling: Thanks, noted, bookmarked, subscribed. BTW the ECS example is only dealing with Errors because it's a concept I thought people would grasp and relate to easily. > yesssss, enums support interfaces!!!!!! Less than five minutes away from the keyboard I realised that this is the key and my problem is solved more elegantly than the initial idea of extending - the interface is perfect, thank you to everyone who pointed it out! I am really impressed how elegant and actually genius the enum implementation is. So well rounded, minimal, yet creates so much value! Re: Rowan: > The concept of "uniqueness" only makes sense within a certain context That's why in ECS example I added the toString() method to the enum, but you're right, I should have named it something along the lines of getErrorPrefix() - and now - using the interface approach I can assure any enum passed to "AddError" will also provide a prefix along with the enum->name (error code) + enum->value (error text) :) > type ApiError = DatabaseError|HttpError; Sounds cool and useful, hope there's motivation enough to see it through, but that's a separate topic, I'm glad this discussion happened, bye now everyone!!

« previous php.internals (#119784) next »