Re: [Early Feedback] Pattern matching

From: Date: Sat, 22 Jun 2024 22:05:18 +0000
Subject: Re: [Early Feedback] Pattern matching
References: 1 2 3 4 5 6 7  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message
On Sat, Jun 22, 2024 at 11:57 PM Robert Landers
<[email protected]> wrote:
>
> On Sat, Jun 22, 2024 at 10:53 PM Rowan Tommins [IMSoP]
> <[email protected]> wrote:
> >
> > On 22/06/2024 19:34, Robert Landers wrote:
> >
> > I've brought this up before, but I mostly see "as" being useful for
> > static analysis. That's what I've mostly used it for C#, anyway.
> > Logically, you know the type, but due to one-thing-or-another you
> > can't "prove" the type is that type (such as foreach-arrays or dealing
> > with results from user-code callbacks in library code). I want to be
> > able to say "this is an int or else."
> >
> >
> > I absolutely see the use case for that; I just don't think "as" is a good
> > word for it, because that's not what it means in normal English.
> >
> >
> > Incidentally, according to the C# docs at https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/type-testing-and-cast#as-operator
> >
> > > The as operator explicitly converts the result of an expression to a given reference
> > > or nullable value type. If the conversion isn't possible, the as operator returns null. Unlike
> > > a cast expression, the as operator never throws an exception.
> >
> > So it more closely matches my intuition: a statement of just "foo as Bar;" would
> > be useless, because it's calculating a value and discarding it, with no side effects.
>
> 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();
> }
>
> With "is" then it looks a little more wonky but isn't far from the
> current instanceof method:
>
> function foo(BarInterface $bar) {
>   if ( $bar is Baz ) $bar->thing();
>   $bar->otherThing();
> }
>
> 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();
>   }
> }
>
> If we were to do an "is" check on the first line, by the time the
> fiber is resumed, we've got a completely different type on our hands
> and it would crash. Maybe that is desirable, maybe not, but we know
> that we have a reference of the type we want and it won't be changed
> under us by using "as."
>
> > As you say, the conversion might not be of the value, but of the statically analysed type,
> > but in C#, that's all part of the language. In PHP "$foo = $bar as SomeInterface;"
> > would have no visible effect except in third-party tooling, where it can already be written
> > "/** @var SomeInterface $foo */ $foo = $bar;"
>
> Hopefully my examples show how it can be useful (at least when it
> returns null if it is the wrong type). When it gives a TypeError or
> something, it becomes far less useful -- at least for the sake of
> conciseness. 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
>
> But even if we did return null, those would crash unless foo() took
> int|null, which may or may not be what you want ...
>
> With it always being an error if it doesn't match, it's really not
> that useful, as you point out.

Side-note: this is why my original proposal had two modes (based on
the existence of null in the typecheck):

foo(123.456 as int);

would crash due to being unable to cleanly cast to int.

foo(123.456 as int|null);

would crash from passing null (since literally everything can be
casted to null and it can't be casted to an int).

>
> >
> >
> > --
> > Rowan Tommins
> > [IMSoP]


Thread (79 messages)

« previous php.internals (#123761) next »