Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:109645 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 67360 invoked from network); 15 Apr 2020 12:34:18 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 15 Apr 2020 12:34:18 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 86D581804C2 for ; Wed, 15 Apr 2020 04:04:12 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-yb1-f182.google.com (mail-yb1-f182.google.com [209.85.219.182]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 15 Apr 2020 04:04:12 -0700 (PDT) Received: by mail-yb1-f182.google.com with SMTP id n2so8940924ybg.4 for ; Wed, 15 Apr 2020 04:04:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=A1sBuH3AkUIQ6LN6QtlTP7ixh6/UxAY1lPjgmiAKIaQ=; b=aHazYElkcjBSP0Y8P3bNiFk12drMU3nKLi/Grdzgok5CbMMFILNuIgNKxy2kElrctG 5fuZvEFK/1Dlrj7lwgUy6/EUFJumGFZI8IlvIry2EUE6t4EkQyIT/4EHMXttuWZ1T/6a 9zXgZMKJU4WRqP7RqarEVKN0WvRBNXbHuyaJhxg75zI+LW9wI0VsZ//Qzta+71QZ8aFq d7ptHzsU4o2KFsw3zD0kI03PtFEYTAdJGk81UVXJCDaMqL8mCRps5z3y6Cdt470/jrQh YKmVxu9NPmMbuAmTB7aBpNfDSu+8ZCHSzQvofvcHClb+LFxMbEsCEOunDD7bjod8VAVP fmmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=A1sBuH3AkUIQ6LN6QtlTP7ixh6/UxAY1lPjgmiAKIaQ=; b=UlCTfHyJ4RcLgLWLzvJEY1jMd+zTEZ8JjsCpcrwIbSo8j3WX+18rA7V0mXZwj57FeW wCrtHT3kEvh+jl6qGjHTRO6A46YwCRtRcCri/XjGGNKIsGIRll6i8Ob/0lxmSheJuS1F a1KDfKWSLFkXKhyJyF3m00i/bpjBtOKi+1/ErO5PVpO8BK7r+SmD4dOVoQoPcC3lwls4 lYhMUSlSlnb5x06dWqqieXCTJU2iALp9uBst93zqO8LPv5SPISTB2UumpSrzQ8WgvPWC uQj+PULULowI4Sw6CoiSTmHXR7RE9zhU0dqKPFHesSRBWOBV1O2E5rym7pBm0tJggL25 tZ/A== X-Gm-Message-State: AGi0PuZaknSaVzprp0eSuURghNczI+9r9OnxWN2TkY6I3DiEqFzBVUb9 nFM9BYmcoLlWAIQOxvZgItsXbxxXddGEEOSYJ80Gff3i X-Google-Smtp-Source: APiQypLbvKZ+feCBRP3JGLyQIefvEJRwHsPfJngugyQO5VxO5ozgn2i3pRNloCiBDGVMS2gu0ag7tcsTi7ha3MsMR4w= X-Received: by 2002:a5b:850:: with SMTP id v16mr7585490ybq.347.1586948649392; Wed, 15 Apr 2020 04:04:09 -0700 (PDT) MIME-Version: 1.0 References: <5e94f84b.1c69fb81.8f1da.317bSMTPIN_ADDED_MISSING@mx.google.com> <5e9621b0.1c69fb81.b7fda.5601SMTPIN_ADDED_MISSING@mx.google.com> In-Reply-To: <5e9621b0.1c69fb81.b7fda.5601SMTPIN_ADDED_MISSING@mx.google.com> Date: Wed, 15 Apr 2020 13:03:58 +0200 Message-ID: To: PHP internals Content-Type: text/plain; charset="UTF-8" Subject: Re: [PHP-DEV] Re: [DISCUSSION] Match expression From: tovilo.ilija@gmail.com (Ilija Tovilo) Hi Andrea > Well, I don't think we have any other expressions that are also > statements with very slightly different syntax The syntax isn't actually different. We don't have different grammar for the match statement and expression. There's only one. Think of it more like a type check. In other languages you couldn't use the result value of a `void` function (PHP is a little different here since `void` functions return `null`). Similarly using the result of `{ ... }` doesn't make sense (as it has none) so we throw a compilation error. Alternatively we could return `null` here too but I'd really prefer not to. > We already have a limited kind of pattern matching in PHP While that's true I don't think the array pattern should be implemented in the same way. There's a lot to think about here. For example: ``` // Traditional array destructuring [$a, $b] = [1, 2, 3]; //> $a === 1 //> $b === 2 ``` This is usually not how array patterns work. The array size is critical: ``` let [$a, $b, $c] = [1]; // Unmatched pattern error let [$a] = [1, 2]; // Unmatched pattern error let [$a, $b, $c] = [1, 2, 3]; // Ok let [$a, ...] = [1, 2]; // Ok ``` There are more things to think about like allowing `ArrayAccess&Countable`, order, `[$x, ...$y]`, etc. If we get the details wrong it might be hard to correct them later. Another challenge is emitting efficient opcodes. Consider this example: ``` let [1, 2, $c] = $value; // Is roughly equivalent to: if ( !is_array($value) || count($value) !== 3 || !isset($value[0]) || $value[0] !== 1 || !isset($value[1]) || $value[1] !== 2 || !isset($value[2]) ) { throw new UnmatchedPatternError(); } $c = $value[2]; ``` Since PHP (often) doesn't have enough type information at compile time the number of opcodes can explode very quickly due to many runtime checks. I don't know how we would best tackle this yet. Another issue is scoping that is pretty hard to solve in PHP. ``` $x = 10; match ([1, 2]) { let [$x, 3] => ..., default => ..., } // $x is now 1 even though the pattern did not match ``` The values shouldn't be assigned until after the pattern has matched which means more complexity and less efficiency. I hope you can see now why I'm hesitant here. > It would be a bit surprising if you are new to the `match` statement So surprising in fact I'm willing to bet 90% would get it wrong the first time (if uninstructed, of course). > True, that is less elegant. But when would you need to do that? Anytime you would've written code like this: ``` if ($x === $foo) { $y = ...; } elseif ($x === $bar) { $y = ...; } ``` This is not uncommon at all. With match + arbitrary lhs expressions you can replace it with: ``` $y = match ($x) { $foo => ..., $bar => ..., }; ``` The switch probably wouldn't have been used here because it's even more verbose than the if (and more error prone). ``` switch ($x) { case $foo: $y = ...; break; case $bar: $y = ...; break; } ``` Ilija