On Tue, 4 Feb 2025 at 07:35, Larry Garfield <la...@garfieldtech.com> 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 > Hi, Larry! First of all, I'm very excited about your Pattern Matching RFC and looking forward to it. > Because PHP uses only an LL(1) parser Are there any plans to upgrade the parser to bypass these limitations? I remember Nikita shared some thoughts on why this is not trivial in https://wiki.php.net/rfc/arrow_functions_v2. Maybe something has changed since then? -- Valentin