instance version of match ?

php.internals

Karoly Negyesi

4 years ago
Hi, May I suggest adding a little "instanceof" magic to match? Like this: match ($object) { Someinterface => 'foo', AnotherInterface => 'bar', } this can not clash with any existing code as using identifiers like this are a syntax error currently. Currently you could do the same with match (true) { $object instanceof Someinterface::class => 'foo', $object instanceof AnotherInterface::class => 'bar', } Indeed, the former could be considered syntactic sugar for the latter. And I do not think there's any ambiguity here for the casual reader or is it just me who thinks no other sensible reading is possible? Thanks for your consideration. Karoly Negyesi

Weirdan

4 years ago
On Mon, Mar 28, 2022 at 7:56 PM Karoly Negyesi <karoly@negyesi.net> wrote:
> match ($object) { > Someinterface => 'foo', > AnotherInterface => 'bar', > } > > this can not clash with any existing code as using identifiers like this > are a syntax error currently.
That's valid code actually, see https://3v4l.org/BEcE4

Robert Landers

4 years ago
On Tue, Mar 29, 2022 at 3:47 AM Bruce Weirdan <weirdan@gmail.com> wrote:
> > On Mon, Mar 28, 2022 at 7:56 PM Karoly Negyesi <karoly@negyesi.net> wrote: > > match ($object) { > > Someinterface => 'foo', > > AnotherInterface => 'bar', > > } > > > > this can not clash with any existing code as using identifiers like this > > are a syntax error currently. > > That's valid code actually, see https://3v4l.org/BEcE4 > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php >
It can be modified to produce ambiguous code however: const SomeInterface = 1; const AnotherInterface = 2; interface SomeInterface {} interface OtherInterface {} $object = new class implements SomeInterface {}; var_dump( match (true) { $object instanceof SomeInterface => 'foo', $object instanceof AnotherInterface => 'bar', } ); We can see that `SomeInterface` will resolve the interface and not the constant. I think what they are proposing is that when the match is an object, and the branches are class/interface/etc names, it should just do an `instanceof` operation instead of a value-equals operation.

Rowan Collins

4 years ago
On 29/03/2022 11:59, Robert Landers wrote:
> $object instanceof AnotherInterface => 'bar', > > We can see that `SomeInterface` will resolve the interface and not the > constant.
Yeah, the instanceof operator is magic in that regard - it has a special parsing rule to consume the next token and avoid it being evaluated as a constant.
> I think what they are proposing is that when the match is an object, > and the branches are class/interface/etc names, it should just do an > `instanceof` operation instead of a value-equals operation.
That wouldn't work, because the type of value passed to match() can vary at run-time, but you'd need to compile the expression one way or the other. If it did work, it would be extremely confusing: function example(string|object $input) {     return match($input)  {           SomeClass => 'found class',          SOME_CONSTANT => 'found constant',     }; } var_dump( example(new SomeClass) ); var_dump( example(SOME_CONSTANT) ); Do both of those matches succeed? What if I set `const SomeClass = 'hello';`? So unfortunately we need some extra syntax to say that something should be an instanceof check, and therefore a class name. Regards,
-- Rowan Tommins [IMSoP]

Thomas Nunninger

4 years ago
Hi, Am 29.03.22 um 14:34 schrieb Rowan Tommins:
> On 29/03/2022 11:59, Robert Landers wrote: >>          $object instanceof AnotherInterface => 'bar', >> >> We can see that `SomeInterface` will resolve the interface and not the >> constant. > > > Yeah, the instanceof operator is magic in that regard - it has a special > parsing rule to consume the next token and avoid it being evaluated as a > constant. > > >> I think what they are proposing is that when the match is an object, >> and the branches are class/interface/etc names, it should just do an >> `instanceof` operation instead of a value-equals operation. > > > That wouldn't work, because the type of value passed to match() can vary > at run-time, but you'd need to compile the expression one way or the other. > > If it did work, it would be extremely confusing: > > function example(string|object $input) { >     return match($input)  { >           SomeClass => 'found class', >          SOME_CONSTANT => 'found constant', >     }; > } > var_dump( example(new SomeClass) ); > var_dump( example(SOME_CONSTANT) ); > > Do both of those matches succeed? What if I set `const SomeClass = > 'hello';`? > > > So unfortunately we need some extra syntax to say that something should > be an instanceof check, and therefore a class name.
While I liked the intention of Karoly, I did not like the proposed magic. Would it be an idea (and possible) to extend the syntax somehow like: $result = match ($value) { instanceof MyObject => ...,
>= 42 => ...,
!== 5 => ... }; to be equivalent to: $result = match (true) { $value instanceof MyObject => ..., $value >= 42 => ..., $value !== 5 => ... }; Regards Thomas

Arnaud.lb

4 years ago
On mardi 29 mars 2022 15:33:41 CEST Thomas Nunninger wrote:
> Hi, > > Am 29.03.22 um 14:34 schrieb Rowan Tommins: > > On 29/03/2022 11:59, Robert Landers wrote: > >> $object instanceof AnotherInterface => 'bar', > >> > >> We can see that `SomeInterface` will resolve the interface and not the > >> constant. > > > > Yeah, the instanceof operator is magic in that regard - it has a special > > parsing rule to consume the next token and avoid it being evaluated as a > > constant. > > > >> I think what they are proposing is that when the match is an object, > >> and the branches are class/interface/etc names, it should just do an > >> `instanceof` operation instead of a value-equals operation. > > > > That wouldn't work, because the type of value passed to match() can vary > > at run-time, but you'd need to compile the expression one way or the > > other. > > > > If it did work, it would be extremely confusing: > > > > function example(string|object $input) { > > > > return match($input) { > > SomeClass => 'found class', > > SOME_CONSTANT => 'found constant', > > }; > > > > } > > var_dump( example(new SomeClass) ); > > var_dump( example(SOME_CONSTANT) ); > > > > Do both of those matches succeed? What if I set `const SomeClass = > > 'hello';`? > > > > > > So unfortunately we need some extra syntax to say that something should > > be an instanceof check, and therefore a class name. > > While I liked the intention of Karoly, I did not like the proposed magic. > > Would it be an idea (and possible) to extend the syntax somehow like: > > $result = match ($value) { > instanceof MyObject => ..., > > >= 42 => ..., > > !== 5 => ... > }; > > to be equivalent to: > > $result = match (true) { > $value instanceof MyObject => ..., > $value >= 42 => ..., > $value !== 5 => ... > }; > > > Regards > Thomas
I like this. The pattern matching RFC may also cover this: https://wiki.php.net/rfc/pattern-matching -- Arnaud

azjezz

4 years ago
On Tuesday, March 29th, 2022 at 12:55 AM, Karoly Negyesi <karoly@negyesi.net> wrote:
> Hi, >
> May I suggest adding a little "instanceof" magic to match? Like this: >
> match ($object) { >
> Someinterface => 'foo', >
> AnotherInterface => 'bar', >
> } >
> this can not clash with any existing code as using identifiers like this >
> are a syntax error currently. >
> Currently you could do the same with >
> match (true) { >
> $object instanceof Someinterface::class => 'foo', >
> $object instanceof AnotherInterface::class => 'bar', >
> } >
> Indeed, the former could be considered syntactic sugar for the latter. And >
> I do not think there's any ambiguity here for the casual reader or is it >
> just me who thinks no other sensible reading is possible? >
> Thanks for your consideration. >
> Karoly Negyesi
Hi Karoly, As mentioned by Bruce, this syntax is already valid, therefor, it can't be used. what you are looking for is pattern-matching, see "`match()` enhancement" section in the RFC: https://wiki.php.net/rfc/pattern-matching Regards, Saif Eddin Gmati.