Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129571 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 945AC1A00BC for ; Mon, 8 Dec 2025 15:43:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1765208601; bh=7uIgh9yOZcXCkPxvHVePc4C6ZJQn9qseMpS4rdcvzdk=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=AreyBH2XZDLoiVHqjJzqMVd27BNvfY7ikM+ntzQBCjat6Agli2txstX5U+qNL6rn0 Ov+vEJ65Ft8wHPU+HrobYudKYbA6Tyosc/bKJpczrgnwM5KLOyBj9Q4dDStOVWYEor fmWY4GTOMqh1NyGYBnsipTG2aSISRa0gMryabg9gpefzw0VZ8blE1LjqKntsIXK8lR 4CNZ1ebx5P2DUf7tfsJ8JQ+DcP1CoS4fXebS/GJpScZzPUbUEifp6o5h/YVkxaD+dc K5JrhBCt3nwIodmlSH71TyllNSMRa5m9lXXvuyFr+kH57He4abJ+yYB5ZEho3KCSjN 7+nzq87TCWWbw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id E0405180034 for ; Mon, 8 Dec 2025 15:43:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from chrono.xqk7.com (chrono.xqk7.com [176.9.45.72]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 8 Dec 2025 15:43:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bastelstu.be; s=mail20171119; t=1765208592; bh=K+SvgZupnHBF4tQEF6qnZTPLEjV9sg37139mOlUPGxA=; h=MIME-Version:Date:From:To:Cc:Subject:In-Reply-To:References: Message-ID:Content-Type:from:to:cc:subject:message-id; b=Dj6SWYsp//T2rpn96WzzuDtI0cQJ6mdTjGx1S4SEq9ACR336PvHTboWe0W4a8YIuf +dZKAI3kCaE7IhJtK3PLOK3PktJCOlSqyf153187kQ9UHv5Kv/+RZjjOzaDNs2ZYw+ sS4mrecOIjpebKBdgp9/r0XnwhdxQUmrRLaCWd+xPTcCFsRB9XXs81DvLna3RJzE65 x42k0Efx5KzQZLE1WNaabfg8str4j0HZzTAF7MYodUwshB5/w3YHeN5ZTaY0UqrlfT Sdcs7Efu6TAfNSIxT7XA6r9M9lMe5PpqpHZJ7EmurY/m31ODRscOp9PoonpmHfjuTo yMynR+bMGcApQ== Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 Date: Mon, 08 Dec 2025 16:43:12 +0100 To: Larry Garfield Cc: php internals Subject: Re: [PHP-DEV] [RFC] Pattern Matching In-Reply-To: References: Message-ID: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: tim@bastelstu.be (=?UTF-8?Q?Tim_D=C3=BCsterhus?=) Hi Am 2025-12-01 22:36, schrieb Larry Garfield: > Hi folks. Ilija and I would like to present our latest RFC endeavor, > pattern matching: > > https://wiki.php.net/rfc/pattern-matching Thank you. I've already provided some feedback on the PR (and in Ilija's DMs) after seeing it “show up” in php-src, but I promised to put it on-list. I'm doing that now. This email is not a full review of the RFC, just the parts that I already noted. I think I also noted them before in the previous on-list “pre RFC” discussion. 1. I'd like to see `$foo is $bar` with a single top-level variable binding on the right side disallowed at compile time. This pattern is just an elaborate way of writing an assignment, thus (almost) never useful, but possibly confusing to folks coming from Python or just generally unfamiliar with PHP's pattern matching. I'd be okay with allowing `$foo is ($bar)` with the explicit parentheses, since this is an established pattern to indicate “yes, I meant it like this” when using assignments inside of conditionals, such as `while (($row = $statement->fetch()))` as a short form of `while (($row = $statement->fetch()) !== false)`. 2. I'd like to see required parentheses around “combinator patterns” (specifically `&` and `|`). The RFC currently claims: > While patterns may resemble other language constructs, whatever follows > is is a pattern, not some other instruction. which is false. “Whatever follows is a pattern, unless it no longer is a pattern” would be more accurate, which is not very helpful to intuitively determine the end of a pattern when visually scanning the code, particularly with the spacing around the combinators that the RFC suggests. The main issue is that pattern matching embeds a DSL with its own syntax inside of PHP, but without having a clear “pattern ends here delimiter”. I've also looked at other programming languages with pattern matching and most only support pattern matching at a small number of “special locations” (e.g. as part of a `match()` construct or only within a function signature) and also do not have a concept of “union” or “intersection” patterns. PHP allows to embed patterns (and the associated DSL) into arbitrary (complex) expressions, which is not something that is commonly seen as far as I can tell. C# appears to support it as well, but the overall syntax for pattern matching is quite different there, which makes it hard to directly compare it. The “atomic patterns” as a top-level are fine, since they are either a single “word” without any spaces or already have clear delimiters (such as the array pattern). To give an example: Consider line wrapping within a single pattern (e.g. because the class names get long or because the pattern matching expression is deeply indented). The most natural way I can come up with, without introducing parentheses, is the following: if ( $foo is Foo(some: "stuff", :$here) & Bar(with: "more_stuff") ) { } I find it incredibly non-obvious that `& Bar` still belongs to the pattern. And with just a single non-whitespace character change it becomes something entirely different, but also valid: if ( $foo is Foo(some: "stuff", :$here) && Bar(with: "more_stuff") ) { } I believe it is not unlikely that the former is interpreted as a typo for the latter by someone inexperienced with pattern matching. For `$foo is $bar&?User` there is some ambiguity if that should have been `($foo is $bar) ? User : …` (i.e. a ternary with a constant `User` in the “then” part). It might be clear grammar-wise, but not necessarily immediately to a reader. The proposed pattern matching semantics are extremely powerful, but do not come with any integrated guardrails, which make them extremely complex and easy to “hold wrong”. I find this a step backwards from the recent developments making PHP safer and more predictable without forcing users to learn all rules by heart. We already had issues with “gobble up everything until you can't” with short closures and pipes in 8.5. I fear the same happening with pattern matching. As an example the (future scope) range pattern `$foo is 1..=10` can easily be typoed or misremembered as `$foo is 1...10` which to my understanding would be valid PHP code equivalent to `($foo is 1.0) . (0.10)` (which is not useful, but valid). Taking into account possible guardrails right away can help ensure that future additions can be added in a way that is consistent with existing “look and feel”. Best regards Tim Düsterhus