On 04.02.25 08:51, Rob Landers wrote:
>
>
> 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
Is it possible to use the already added "is", like:
$arr is ['a' => $a, 'b' => is $b]
Or, to use the already known uniform variable syntax "{$var}", like:
$arr is ['a' => $a, 'b' => {$b}]
Best,
Marc