On Sun, Jun 23, 2024 at 2:19 PM Rowan Tommins [IMSoP]
<imsop....@rwec.co.uk> wrote:
>
>
>
> On 22 June 2024 22:57:24 BST, Robert Landers <landers.rob...@gmail.com> wrote:
> >In general, you assign the result of the operation so that the output
> >is useful. Here's how that might look in PHP with the C# rules:
> >
> >function foo(BarInterface $bar) {
> >  $baz = $bar as Baz;
> >  $baz?->thing();
> >  $bar->otherThing();
> >}
>
>
> The difference is that in C#, there is an actual difference between the 
> methods available on $bar and $baz. The "as" is performing a conversion, so 
> the English word makes sense.
>

Ah, I see what you mean. Yeah, PHP doesn't understand type casts too
well (as in class/interface-types) but they are there, just clunky to
deal with. Here's some real-ish code with a bunch of things stripped
out:

abstract class Event {}

interface HasInnerEvent { public function getInnerEvent(): Event; }

interface DelayedEvent { public function getDelay(): int; }

class ScheduleTask extends Event implements HasInnerEvent, DelayedEvent { ... }

class Signal extends Event { ... }

Then when receiving an event:

function storeEventLocally(DelayedEvent $event): void;
function handleInnerEvent(HasInnerEvent $event): void;

/** @var Event $event */
foreach ($events as $event) {
  if ($event instanceof DelayedEvent) {
    storeEventLocally($event);
    continue;
  }

  if ($event instanceof HasInnerEvent) {
    handleInnerEvent($event);
  }
}

With only "is" it doesn't change much (if at all, structurally), but
with the C# rules, I only need a few changes, and it becomes much more
readable (IMHO):

function storeEventLocally(DelayedEvent|null $event): void;
function handleInnerEvent(HasInnerEvent|null $event): void;

/** @var Event $event */
foreach ($events as $event) {
  storeEventLocally($shouldContinue = $event as DelayedEvent);
  if ($shouldContinue) continue;

  $mainEvent = handleInnerEvent($event as HasInnerEvent);
}

> In PHP, all we could do is have a one-off runtime check, then return the 
> value unchanged. So written out in full, that would be:
>
> function foo(BarInterface $bar) {
>   $baz = null;
>   if ( $bar is Baz ) $baz = $bar;
>   $baz?->thing();
>   $bar->otherThing();
> }
>
> Or:
>
> function foo(BarInterface $bar) {
>   $baz = $bar;
>   if ( ! $bar is Baz ) $baz = null;
>   $baz?->thing();
>   $bar->otherThing();
> }
>
>
> I can see some use in a shorthand for that, but it doesn't have much in 
> common with casts, or any meaning of "as" that I can think of, so I don't 
> think that would be the right name for it.
>

"as" is just fancy casting (usually), but PHP doesn't have any real
casts other than scalars so it makes the feature itself hard to grok,
and tossing in errors makes the entire example I showed completely
pointless because it would fail. In fact, I am not sure what the case
is for an "as" that throws now that I've written it out a few times.

>
>
> >With fibers/async, "as" is actually more important than "is" (at least
> >as far as crashing goes):
> >
> >class Foo {
> >  public BarInterface $bar;
> >
> >  public function doStuff() {
> >    $baz = $this->bar as Baz;
> >    // some stuff with $baz
> >    callComplexThing(); // suspends current fiber,
> >    // $this->bar is no longer the same object
> >    // or concrete type when we return
> >    $baz->something();
> >  }
> >}
>
>
> The thing that's stopping this crashing is not the "as", it's that you're 
> backing up the old value of $this->bar into a local variable. Nothing about 
> $baz will "remember" that you made some type or pattern check against it just 
> before/after you assigned it.

I was pointing out issues with the inherent patterns they propose, but
you're not wrong. :)

>
>
>
> >However, it becomes far more useful to dealing with
> >scalar casts:
> >
> >function foo(int $type) {}
> >
> >foo(123.456 as int); // crashes
> >foo(null as int); // crashes
>
>
> Yes, those are actually casts/conversions in PHP, and I've repeatedly said 
> I'd like to have those, on top of the "never fail" casts we have now. Whether 
> that's with an "as" operator, a "cast" function, or some extension of the 
> existing cast syntax, is an open question.
>
> Crucially, though, I don't think most *patterns* would be relevant in that 
> context, as I pointed out in a previous message.
>
>
> Regards,
> Rowan Tommins
> [IMSoP]

Reply via email to