On Wed, 29 Mar 2023 at 18:40, Larry Garfield <la...@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:
>
> 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!!

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to