Re: [PHP-DEV] Type casting syntax

This is only part of a thread. view whole thread
  115412
July 12, 2021 17:01 mike@newclarity.net (Mike Schinkel)
> On Jul 12, 2021, at 11:00 AM, Larry Garfield <larry@garfieldtech.com> wrote: > x > On Mon, Jul 12, 2021, at 9:54 AM, Max Semenik wrote: > >> I was thinking of something akin to many compiled languages' approach of >> "consider this expression is now of that type, and throw an exception if >> it's not". An example of this approach from Benjamin's proposal of old^ >> >> $service = (EmailService) $diContainer->get('email.service'); >> >> Instead of >> >> /** @var EmailService $service */ >> $service = $diContainer->get('email.service'); >> if (!$service instanceof EmailService) { >> throw new TypeError('Expected instance of EmailService, ...'); >> } > > Hm, that's a different creature. I... would be probably OK with something in that direction, though I wouldn't work on it myself. I think what you're describing here is more of a type assertion. "Assert that this variable is of type X, otherwise bail." So, some kind of non-disableable (or maybe disableable?) shorthand for `assert($foo instanceof Bar)`.
Regarding prior art on type assertion, the syntax Go uses is `value.(type)` so using a similar approach in PHP might look like this (I'm spitballing by using the double colon as a sigil but it could anything that doesn't conflict with existing usage, whatever those options are): $service = $diContainer->get('email.service')::(EmailService); Additionally in Go a type assertion can return a second value which is boolean telling if the type assertion succeeded. Not having this would effectively moot the benefit to a type assertion if you had to wrap with try{}catch{} in case it failed. $service, $okay = $diContainer->get('email.service')::(EmailService); if (!$ok) { echo 'Not an EmailService.'; } #fwiw -Mike
  115413
July 12, 2021 17:56 maxsem.wiki@gmail.com (Max Semenik)
On Mon, Jul 12, 2021 at 8:01 PM Mike Schinkel <mike@newclarity.net> wrote:

> Additionally in Go a type assertion can return a second value which is > boolean telling if the type assertion succeeded. Not having this would > effectively moot the benefit to a type assertion if you had to wrap with > try{}catch{} in case it failed. >
Not necessarily: if ($obj instanceof MyClass) { // We know its type here } else { // Try something else } -- Best regards, Max Semenik
  115415
July 12, 2021 20:20 mike@newclarity.net (Mike Schinkel)
> On Jul 12, 2021, at 1:56 PM, Max Semenik wiki@gmail.com> wrote: > > On Mon, Jul 12, 2021 at 8:01 PM Mike Schinkel <mike@newclarity.net <mailto:mike@newclarity.net>> wrote: > Additionally in Go a type assertion can return a second value which is boolean telling if the type assertion succeeded. Not having this would effectively moot the benefit to a type assertion if you had to wrap with try{}catch{} in case it failed. > > Not necessarily: > > if ($obj instanceof MyClass) { > // We know its type here > } else { > // Try something else > }
Well there you go. It seems you have just illustrated why in reality we really do not need type casting/assertions in PHP given its current features, because we already have what we need. -Mike
  115416
July 12, 2021 20:28 kjarli@gmail.com (Lynn)
On Mon, Jul 12, 2021 at 10:20 PM Mike Schinkel <mike@newclarity.net> wrote:

> It seems you have just illustrated why in reality we really do not need > type casting/assertions in PHP given its current features, because we > already have what we need. >
That's not an argument I agree with, as it would invalidate the need for short closures, null coalesce, constructor property promotion, etc. Continuing on the previous example: ```php $service = $container->get(SomeService::class); assert($service instanceof SomeService); // could be replaced with $container->get(); // or in case of multiple instances: $container->get('the.service.alias'); // perhaps the service is optional $container->get(); ```
  115417
July 12, 2021 20:36 mike@newclarity.net (Mike Schinkel)
> On Jul 12, 2021, at 4:28 PM, Lynn <kjarli@gmail.com> wrote: > On Mon, Jul 12, 2021 at 10:20 PM Mike Schinkel <mike@newclarity.net <mailto:mike@newclarity.net>> wrote: > It seems you have just illustrated why in reality we really do not need type casting/assertions in PHP given its current features, because we already have what we need. > > That's not an argument I agree with, as it would invalidate the need for short closures, null coalesce, constructor property promotion, etc. > > Continuing on the previous example: > ```php > $service = $container->get(SomeService::class); > assert($service instanceof SomeService); > > // could be replaced with > $container->get();
In your hypothetical view here, what happens when the $container does not have SomeService to provide? Does it throw an Exception? -Mike
  115419
July 12, 2021 21:16 kjarli@gmail.com (Lynn)
On Mon, Jul 12, 2021 at 10:36 PM Mike Schinkel <mike@newclarity.net> wrote:

> > In your hypothetical view here, what happens when the $container does not > have SomeService to provide? Does it throw an Exception? > > Up to the developer that implements it. If the signature would be
`get(?string $id): T;` then I would assume an error should be thrown by PHP, or an Exception by the method, or handled by the developer to always return `T`. `?SomeException` as `T` could let the developer not throw an exception if needed and return `null` instead.
  115418
July 12, 2021 21:00 maxsem.wiki@gmail.com (Max Semenik)
On Mon, Jul 12, 2021 at 11:20 PM Mike Schinkel <mike@newclarity.net> wrote:

> It seems you have just illustrated why in reality we really do not need > type casting/assertions in PHP given its current features, because we > already have what we need. >
Heh, nope - you asked for handling of such cases without exceptions, I obliged. My plans were around different usage scenarios. In any case, I'm not making a proposal at this point, I'm just enquiring about syntax. If I ever get something proposable done, I'll make a formal RFC. -- Best regards, Max Semenik