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
la...@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

Attachment: OpenPGP_0x3936ABF753BC88CE.asc
Description: OpenPGP public key

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to