Hi Larry,

Thank you for the comment.

> It seems like what you're describing here is more user-customizable 
> autoboxing than anything to do with union types.  

Your first statement ("user-customizable autoboxing") is probably fair to say.

OTOH, rather than say "anything to do with union type" I would instead say 
"where union-types is an excellent use-case for auto-boxing."

> For that, it seems like you'd want more of a fromString() method (magic or 
> interface):

That would certainly work. 

But unfortunately that requires the class developer to be forward-thinking 
enough to implement methods required for all the use-cases of their class 
users, and I think it is unlikely we can depend on that case for most classes 
in the wild.

What I'd rather see is a solution that gives the user of the class more control 
and a well-known/consistent programming model (e.g. ->toGuid().)


> Whether or not something like that is wise I don't know, but it seems like it 
> would resolve the use case you describe better than fiddling with union 
> types.  Or am I totally misunderstanding you as well? :-)

I made the proposal because I felt that auto-boxing was the best solutions for 
the union-types use-case.  So if renaming the proposal to "user-customizable 
autoboxing" is more preferred by others I'd see that to be fine, assuming it 
was implemented in a manner that allowed for adding the use-case of union 
types. :-)

-Mike

P.S. I am not seeing much traction from this proposal so even though we discuss 
the nuances it seems likely it won't matter beyond this discussion.


> On Sep 11, 2019, at 6:07 AM, Larry Garfield <la...@garfieldtech.com> wrote:
> 
> On Sun, Sep 8, 2019, at 2:11 PM, Mike Schinkel wrote:
>> Hi Stephen,
>> 
>> Thanks again.
>> 
>>> So let me start out by clarifying that what *I* was suggesting with unions 
>>> is quite a different concept than you’re talking about. 
>> 
>> I did not realize you were proposing a different solution, too. Sorry I 
>> missed that.
>> 
>>> yes, I’m aware there’s potential ambiguous cases - what if the destination 
>>> accepts `string|int` and the object supports both interfaces?
>> 
>> 
>> Precisely. And the goal of my proposal was in part to eliminate that 
>> ambiguity.
>> 
>>> Ok - the example given makes “sense” with the understanding that it’s 
>>> alternative ‘short’ syntax - but that makes it yet another step further 
>>> from ‘intuitive’ to me, compared with current type hints, and the extension 
>>> to allow unions Nikita introduced -
>> 
>> Acknowledged.
>> 
>>> and if Im not mistaken it makes it incompatible too (i.e. you can’t have 
>>> the behaviour Nikita’s RFC describes and what you describe with the 
>>> ‘anonymous unions’ - they’re too very different approaches using the same 
>>> syntax.
>> 
>> I do not see how they are incompatible except for the details mine 
>> changes, but maybe that is moot at this point?
>> 
>>> I think the intuitiveness factor is easier to explain if you consider the 
>>> case of the Number example - plenty of things will work exactly as you 
>>> expect if you use either an int or a float. But then with your proposal 
>>> suddenly you don’t have a scalar variable any more - yes I know you can 
>>> call `value()` - part of the point of type hints is to reduce boilerplate 
>>> with type checking arguments within the function body - and now you have to 
>>> call a method to get a usable value anyway?
>> 
>> I do not see any technical reason why mine would not be able to behave 
>> the same using the magic methods you were proposing such as 
>> __toString() and for other scalar types — since fundamentally the 
>> proposed union type would be a class anyway. When used that way it 
>> would nullify the benefit of the explicit typing, but if that is what 
>> the developer wanted who was using then why not?
>> 
>> In that context it would be almost the same as just passing in a scalar.
>> 
>>> The GUID example still confuses me in terms of how your example ‘helps’. If 
>>> $guid->getGuid returns null (signifying it’s a string?) presumably I still 
>>> want to do something with that string - otherwise I wouldn’t have accepted 
>>> it as a valid type - at which point I might as well just do a `instanceof` 
>>> or `is_string` call - but now I have to check if the value I was given is 
>>> null, even if I didn’t specify the parameter as being nullable?
>> 
>> It does not help that way. The main help is with $guid->type() which 
>> can be used in a switch. It's just cleaner code, though I can 
>> appreciate that some might see this as not really a benefit:
>> 
>> function processGuid(string|Guid $guid) {
>>      switch( $guid->type()) {
>>              case 'Guid':
>>                      $guid->toGuid()->doSomething();
>>                      break;
>>              case 'string':
>>                      $g = new Guid($guid->toString());
>>                      $g-> doSomething();
>>                      break;
>>      }
>> }
>> 
>> The other benefit is that it becomes a first-class concern that can be 
>> extended when named union classes are used so I could implement this 
>> inside the union class and use it in many functions like this, if I 
>> wanted, rather than have to use type checking boilerplate in Every. 
>> Single. Function:
>> 
>> class GuidUnion {
>> types string|Guid
>> public function doSomething() {
>>      switch( $this->type()) {
>>              case 'Guid':
>>                      $this->toGuid()->doSomething();
>>                      break;
>>              case 'string':
>>                      $g = new Guid($this->toString());
>>                      $g-> doSomething();
>>                      break;
>>      }
>> }
>> }
>> 
>> /**
>> * HERE is where you start seeing a real benefit...
>> */
>> function processGuid1(GuidUnion $guid) {
>>      $guid->doSomething();
>> }
>> function processGuid2(GuidUnion $guid) {
>>      $guid->doSomething();
>> }
>> function processGuid3(GuidUnion $guid) {
>>      $guid->doSomething();
>> }
>> 
>> 
>>> I think (or I hope so at least) we’re at least both clear what the other is 
>>> talking about now.
>> 
>> Hopefully, with that last point clarified, yes.
>> 
>> Thanks again.
>> 
>> -Mike
> 
> It seems like what you're describing here is more user-customizable 
> autoboxing than anything to do with union types.  Viz, since a Guid has a 
> natural and round-trippable string representation, you want to be able to ask 
> for a Guid, be given a string, and then work with it as a Guid either way.
> 
> For that, it seems like you'd want more of a fromString() method (magic or 
> interface):
> 
> class Guid implements FromStringInterface {
> 
>  public static function fromString(string $s) {
>    if (is_valid_guid($s)) {
>      return new static($s);
>    }
>    throw new \TypeError();
>  }
> }
> 
> function needGuid(Guid $g) {
>  $g->doGuidThings();
> }
> 
> 
> needGuid('a9d05a5f-e643-441e-8784-cfd613072072');
> 
> Whether or not something like that is wise I don't know, but it seems like it 
> would resolve the use case you describe better than fiddling with union 
> types.  Or am I totally misunderstanding you as well? :-)
> 
> --Larry Garfield
> 
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
> 

Reply via email to