Re: Pattern matching details questions
| From: | Rob Landers | Date: | Tue, 04 Feb 2025 07:51:20 +0000 |
| Subject: | Re: Pattern matching details questions | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-126279@lists.php.net to get a copy of this message | ||
On Tue, Feb 4, 2025, at 05:31, Larry Garfield wrote:
> Hi folks. Ilija is still working on the implementation for the pattern matching RFC, which we
> want to complete before proposing it officially in case we run into implementation challenges.
>
> Such as these, on which we'd like feedback on how to proceed.
>
> ## Object property patterns
>
> Consider this code snippet:
>
> class C {
> public $prop = 42 is Foo{};
> }
>
> The parser could interpret this in multiple ways:
>
> * make a public property named $prop, with default value of "the result of
>
42 is Foo" (which would be false), and then has an empty (and
> therefore invalid) property hook block
> * make a public property named $prop, with default value of "whatever the result of
> 42 is Foo {}" (which would be false).
>
> Since the parser doesn't allow for ambiguity, this is not workable. Because PHP uses only
> an LL(1) parser, there's no way to "determine from context" which is intended, eg, by
> saying "well the hook block is empty so it must have been part of the pattern before it."
>
> In practice, no one should be writing code like the above, as it's needlessly nonsensical
> (it's statically false in all cases), but the parser doesn't know that.
>
> The only solution we've come up with is to not have object patterns, but have a property
> list pattern that can be compounded with a type pattern. Eg:
>
> $p is Point & {x: 5}
>
> Instead of what we have now:
>
> $p is Point{x: 5}
>
> Ilija says this will resolve the parsing issue. It would also make it possible to match
> $p is {x: 5}, which would not check the type of $p at all, just that
> it's an object with an $x property with value 5. That is arguably a useful feature in some
> cases, but does make the common case (matching type and properties) considerably more clunky.
>
> So, questions:
>
> 1. Would splitting the object pattern like that be acceptable?
> 2. Does someone have a really good alternate suggestion that wouldn't confuse the parser?
>
> ## Variable binding and pinning
>
> Previously there was much discussion about the syntax we wanted for these features. In
> particular, variable binding means "pull a sub-value out of the matched value to its own
> variable, if the pattern matches." Variable pinning means "use some already-existing
> variable here to dynamically form the pattern." Naturally, these cannot both just be a
> variable name on their own, as that would be confusing (both for users and the engine).
>
> For example:
>
> $b = '12';
>
> if ($arr is ['a' => assign to $a, 'b' => assert is equal to $b]) {
> print $a;
> }
>
> Based on my research[1], the overwhelming majority of languages use a bare variable name to
> indicate variable binding. Only one language, Ruby, has variable pinning, which it indicates with a
> ^ prefix. Following Ruby's lead, as the RFC text does right now, would yield:
>
> $b = '12';
>
> if ($arr is ['a' => $a, 'b' => ^$b]) {
> print $a;
> }
>
> That approach would be most like other languages with pattern matching.
>
> However, there is a concern that it wouldn't be self-evident to PHP devs, and the variable
> binding side should have the extra marker. Ilija has suggested &, as that's what's
> used for references, which would result in:
>
> $b = '12';
>
> if ($arr is ['a' => &$a, 'b' => $b]) {
> print $a;
> }
>
> There are two concerns with this approach.
>
> 1. The & could get confusing with an AND conjunction, eg, $value is int
> & &$x (which is how you would bind $value to $x iff it is an integer).
> 2. In practice, binding is almost certainly going to be vastly more common than pinning, so it
> should likely have the shorter syntax.
>
> There are of course other prefixes that could be used, such as
> let (introduces a new keyword, possibly confusing as it
> wouldn't imply scope restrictions like in other languages) or var
> (no new keyword, but could still be confusing and it's not obvious which side
> should get it), but ^ is probably the only single-character option.
>
> So, question:
>
> 1. Are you OK with the current Ruby-inspired syntax? ($a means bind, ^$b means pin.)
> 2. If not, have you a counter-proposal that would garner consensus?
>
>
> Thanks all.
>
> [1]
> https://github.com/Crell/php-rfcs/blob/master/pattern-matching/research.md
>
> --
> Larry Garfield
> larry@garfieldtech.com
>
Hey Larry,
Instead of symbols, why not use words?
We already have &&, but it looks like this uses & instead, which is a bitwise-and. But
the language does have “and” as a keyword.. So instead of:
$value is int & &$x
It would be:
$value is int and &$x
Which removes the confusion you mentioned before (also for someone like me who uses bitwise-and
quite a bit).
— Rob