Union Type (singular) straw man proposal

  106866
September 5, 2019 05:30 mike@newclarity.net (Mike Schinkel)
Hello all,

I'll start by saying I've been lurking for about six weeks and reading everything on the list since then although I was on the list for a short period many years ago.  

I recently took on a role as "WordPress Engineering Team Lead" and as such have gotten much more interested in revisiting PHP's feature set hence why I rejoined the list.  I've been working with PHP for 12 years, programming professionally for 32 years and GoLang the last 1+ years. So while I specialize in WordPress and PHP/MySQL, my experience has been in other frameworks and languages for most of my professional programming career.

I have been planning to write up an RFC regarding union types, but had not found the time. Seeing that Nikita has started a new RFC for Union Types v2 — how do you all keep up with that guy?!? — I realized that I better get these ideas at somewhat documented and presented or the train will have fully left the station.

What I am proposing can be layered on top of Nikita's proposal, and was influenced by what I have learned using Go. It is not a Go feature, but inspired by the Go interface{} type (which is a very different concept compared to interfaces in PHP, btw.)

It is a straw man proposal which means it is not a fully-fleshed out RFC, but if I waited until I had the time to write an RFC then PHP 8 might already be out:

Without further ado:

https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117 <https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117>


Since I'm effectively new to the list this time please go easy on me? :-)

Thanks in advance for all your consideration.

-Mike Schinkel
  106869
September 5, 2019 09:51 come@opensides.be (=?ISO-8859-1?Q?C=F4me?= Chilliet)
Why does the class Number in the example has a $number property and use $this->number->value() rather than $this->value() ?

What is the difference between its getNumber method and its value method?

Is $this->number and $this->number->number pointing the same object or is $this->number->number NULL?

This example is really confusing me more than anything else.

The "function showNumber" example is using $this->number instead of $number I think.

All in all I do not understand the benefits of this approach compared to Nikita’s RFC.
What does this allow you to do that you cannot do without?

Côme
  106885
September 6, 2019 04:22 mike@newclarity.net (Mike Schinkel)
Hi Côme,

> This example is really confusing me more than anything else.
Thank you very much for your feedback. You illustrated perfectly why I should not have produced that proposal in haste. Your confusion was due to my first draft errors, which thanks to your feedback I have hopefully had a chance to correct. I effectively rewrote and extended the proposal which you should be able to find at the same URL: https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117 <https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117> I would be greatly appreciative if you could give is a second look.
> All in all I do not understand the benefits of this approach compared to Nikita’s RFC.
I have moved the benefits to the beginning of the document and expanded the list I elaborate on. Hopefully they will be clear now? -Mike Schinkel P.S. Someone graciously emailed me off list and mentioned that my comments regarding Nikitia sounded like a criticism. If anyone else thought the same — and especially Nikita — please understand I was attempting to praise him but trying to do so in a humorous manner. As the person who emailed me made me realize, sometimes my humor may not translate via a mailing list and especially not for those who are not native English speakers. So I will do my best to avoid using humor on the list in the future. To be clear, I am in awe of Nikita and both his abilities and efforts to benefit the PHP community and greatly appreciate his efforts. I hope that clarifies my earlier intent.
> On Sep 5, 2019, at 4:51 AM, Côme Chilliet wrote: > > Why does the class Number in the example has a $number property and use $this->number->value() rather than $this->value() ? > > What is the difference between its getNumber method and its value method? > > Is $this->number and $this->number->number pointing the same object or is $this->number->number NULL? > > This example is really confusing me more than anything else. > > The "function showNumber" example is using $this->number instead of $number I think. > > All in all I do not understand the benefits of this approach compared to Nikita’s RFC. > What does this allow you to do that you cannot do without? > > Côme
  106886
September 6, 2019 05:20 kalle@php.net (Kalle Sommer Nielsen)
Hi

Den fre. 6. sep. 2019 kl. 07.22 skrev Mike Schinkel <mike@newclarity.net>:
> Thank you very much for your feedback. You illustrated perfectly why I should not have produced that proposal in haste. > > Your confusion was due to my first draft errors, which thanks to your feedback I have hopefully had a chance to correct. I effectively rewrote and extended the proposal which you should be able to find at the same URL: > > https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117 <https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117> > > I would be greatly appreciative if you could give is a second look. > > > > All in all I do not understand the benefits of this approach compared to Nikita’s RFC. > > I have moved the benefits to the beginning of the document and expanded the list I elaborate on. > > Hopefully they will be clear now? > > > -Mike Schinkel
I read both versions of this and it strikes me more as a partical interface that is half baked by using keywords, that is not really in line with how the rest of PHP is designed. This sounds more like something that could be implemented on top of Nikita's RFC if it passes in userland, but anyway, here goes with my comments to this: -- New magical methods that appear out of nowhere without an interface, e.g. ::type(), ::value(), ::setValue(), ::toXZY(). if these magical methods suddenly appear with may be varadic based on the value of the `types` setting, this is inconsistent to the rest of PHP. -- There is no mention of what happens if there is multiple `types` in a definition. -- Why is the syntax using | as a separator where all other decls is using a comma separated list? -- Nitpick The "types" decl doesn't use an ending semicolon in any of your examples -- Nitpick: Your examples in the "Accepting params into a union instance" section uses $this in a procedural function -- In the "Named Union equivalence to anonymous union" section I fail to see how Building2 can magically accept Building, this is based on properties and there is there is no mention of the ability to have (or not to have) multiple named unions as property types. -- Is this designed to be only meant for mutability (You are publically exposing setValue())? -- What happens if the class is extended? -- Why is it desired to implement a namespaced class instance return? If you are working on the object, you should already have access to this information it provides, no? -- Why is ::types() apart of the union instead of leaving that to reflection? No other part of PHP exposes such as a method over procedural functions (like get_object_vars()). (Bear in mind I wrote this as the first in the morning) -- regards, Kalle Sommer Nielsen kalle@php.net
  106887
September 6, 2019 05:32 mike@newclarity.net (Mike Schinkel)
Hi Kalle,

Thank you so much for your feedback.

I am not sure of the list etiquette.  Should I respond to all your points here and possibly generate a lot of emails, or ask that we move the comments to my Gist?

-Mike


> On Sep 6, 2019, at 1:20 AM, Kalle Sommer Nielsen <kalle@php.net> wrote: > > Hi > > Den fre. 6. sep. 2019 kl. 07.22 skrev Mike Schinkel <mike@newclarity.net>: >> Thank you very much for your feedback. You illustrated perfectly why I should not have produced that proposal in haste. >> >> Your confusion was due to my first draft errors, which thanks to your feedback I have hopefully had a chance to correct. I effectively rewrote and extended the proposal which you should be able to find at the same URL: >> >> https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117 <https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117> >> >> I would be greatly appreciative if you could give is a second look. >> >> >>> All in all I do not understand the benefits of this approach compared to Nikita’s RFC. >> >> I have moved the benefits to the beginning of the document and expanded the list I elaborate on. >> >> Hopefully they will be clear now? >> >> >> -Mike Schinkel > > > I read both versions of this and it strikes me more as a partical > interface that is half baked by using keywords, that is not really in > line with how the rest of PHP is designed. This sounds more like > something that could be implemented on top of Nikita's RFC if it > passes in userland, but anyway, here goes with my comments to this: > > -- New magical methods that appear out of nowhere without an > interface, e.g. ::type(), ::value(), ::setValue(), ::toXZY(). if these > magical methods suddenly appear with may be varadic based on the value > of the `types` setting, this is inconsistent to the rest of PHP. > -- There is no mention of what happens if there is multiple `types` in > a definition. > -- Why is the syntax using | as a separator where all other decls is > using a comma separated list? > -- Nitpick The "types" decl doesn't use an ending semicolon in any of > your examples > -- Nitpick: Your examples in the "Accepting params into a union > instance" section uses $this in a procedural function > -- In the "Named Union equivalence to anonymous union" section I fail > to see how Building2 can magically accept Building, this is based on > properties and there is there is no mention of the ability to have (or > not to have) multiple named unions as property types. > -- Is this designed to be only meant for mutability (You are > publically exposing setValue())? > -- What happens if the class is extended? > -- Why is it desired to implement a namespaced class instance return? > If you are working on the object, you should already have access to > this information it provides, no? > -- Why is ::types() apart of the union instead of leaving that to > reflection? No other part of PHP exposes such as a method over > procedural functions (like get_object_vars()). > > (Bear in mind I wrote this as the first in the morning) > > -- > regards, > > Kalle Sommer Nielsen > kalle@php.net
  106889
September 6, 2019 05:34 kalle@php.net (Kalle Sommer Nielsen)
Den fre. 6. sep. 2019 kl. 08.33 skrev Mike Schinkel <mike@newclarity.net>:
> > Hi Kalle, > > Thank you so much for your feedback. > > > I am not sure of the list etiquette. Should I respond to all your points here and possibly generate a lot of emails, or ask that we move the comments to my Gist?
You are welcome to reply both here and in the gist for your readers which may not be reading internals, thank you :) -- regards, Kalle Sommer Nielsen kalle@php.net
  106890
September 6, 2019 06:18 php-lists@koalephant.com (Stephen Reay)
> On 6 Sep 2019, at 11:22, Mike Schinkel <mike@newclarity.net> wrote: > > Hi Côme, > >> This example is really confusing me more than anything else. > > > Thank you very much for your feedback. You illustrated perfectly why I should not have produced that proposal in haste. > > Your confusion was due to my first draft errors, which thanks to your feedback I have hopefully had a chance to correct. I effectively rewrote and extended the proposal which you should be able to find at the same URL: > > https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117 <https://gist.github.com/mikeschinkel/50aec7094f5643223d28674639f9f117> > > I would be greatly appreciative if you could give is a second look. > > >> All in all I do not understand the benefits of this approach compared to Nikita’s RFC. > > I have moved the benefits to the beginning of the document and expanded the list I elaborate on. > > Hopefully they will be clear now? > > > -Mike Schinkel > > P.S. Someone graciously emailed me off list and mentioned that my comments regarding Nikitia sounded like a criticism. If anyone else thought the same — and especially Nikita — please understand I was attempting to praise him but trying to do so in a humorous manner. > > As the person who emailed me made me realize, sometimes my humor may not translate via a mailing list and especially not for those who are not native English speakers. So I will do my best to avoid using humor on the list in the future. > > To be clear, I am in awe of Nikita and both his abilities and efforts to benefit the PHP community and greatly appreciate his efforts. I hope that clarifies my earlier intent. > > >> On Sep 5, 2019, at 4:51 AM, Côme Chilliet wrote: >> >> Why does the class Number in the example has a $number property and use $this->number->value() rather than $this->value() ? >> >> What is the difference between its getNumber method and its value method? >> >> Is $this->number and $this->number->number pointing the same object or is $this->number->number NULL? >> >> This example is really confusing me more than anything else. >> >> The "function showNumber" example is using $this->number instead of $number I think. >> >> All in all I do not understand the benefits of this approach compared to Nikita’s RFC. >> What does this allow you to do that you cannot do without? >> >> Côme >
Hi Mike, From a userland perspective I don’t really “get” your proposal. It seems like you’re trying to allow for type conversions in a predictable manner, but in a very different way than php already does that with built in types and interfaces (__toString, the proposed __toArray, plus the various (de)serialiser options) Your proposal seems to imply some kind of automatic method generation by the engine itself (or the examples are all missing that boilerplate??) which is very non obvious to me and I think would be to others too. From my perspective a more obvious solution for this type of thing (and I’m not necessarily sure I’d use the feature myself to be honest) would be a set of interfaces (or magic methods to match __toString but I know they’re less preferred by some these days) to define that a class can be safely cast to another type when used with typed properties/arguments/returns. Cheers Stephen