Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:109948 Return-Path: <rowan.collins@gmail.com> Delivered-To: mailing list internals@lists.php.net Received: (qmail 58015 invoked from network); 30 Apr 2020 17:08:55 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 30 Apr 2020 17:08:55 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 2DBC21804B4 for <internals@lists.php.net>; Thu, 30 Apr 2020 08:42:37 -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,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,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: <rowan.collins@gmail.com> Received: from mail-il1-f179.google.com (mail-il1-f179.google.com [209.85.166.179]) (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 <internals@lists.php.net>; Thu, 30 Apr 2020 08:42:36 -0700 (PDT) Received: by mail-il1-f179.google.com with SMTP id r2so1777629ilo.6 for <internals@lists.php.net>; Thu, 30 Apr 2020 08:42:36 -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=TCsWzdTbk6WFhQyjxcaJ50QzAv0TfmznbWOxmKv6NBg=; b=GoyGcmA5WgwToG2Mmc/KFLPEWWXjqgyt16hMry4pAfe+kPxGEiNnb5pabvYu4FR0zp Ou2qkoWMjb4p3tQBx5jWoT/W8D4J2uVwi+dBDKem32XmnrlZCHI1dNDybprh430/qLwd 1BZPFDAm9b2gaJs4U7/7bH48jEQosf+8K4cHEazt4Yw42zdCQntZznjxUNIsFQ1J6j1/ zT9ph/tShnLxPF6yuybWk3nbt/s5yspRzrM0iPLNj+tVAHmzUQrRQWecNOSPZ0ZtviCK MiEvQeFJBhzo10xmtEQc2VtTrLAw4v2HiTCd6/TUaNX/2LqIwmut5iA6uP9kYXQrjjKM aAmw== 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=TCsWzdTbk6WFhQyjxcaJ50QzAv0TfmznbWOxmKv6NBg=; b=W3awqk8kjG+5iIqGJ3ZXgOuOQ0YYmo2n4u5XM4/6jbDJTWPjOIoNxbaZHYyIvuP4KG nnSby10njsaQm7Myn2/JNqxqT/TLKt8HSt2LvFmVYEV7VA0b822ufZgJSliMPmbJQlZg yKIgsEPoGPu/wbxybUEZEQNMgJifKC4PA9hIRswyv1n5dofq3V3tYkly+FuKnFzBkzBb at3f/bFGkscafbm/VR4Eg3WuWdovrwYFYRS3yNP12kLieTXDXhOvTddwz2BV5G2psLZ+ S0vOnEAOLI+oXCrCe7v6CSi20ILGQ5bs05Pdj3zcW8wkgAmidvmNRWHhTj9SZRLkUzlm GRSQ== X-Gm-Message-State: AGi0Puar58vtwrNXp+C+6yPCT0nC94mNcok6403dMYQQLEd897ImR1pE UYmYd8F17h5CyZ9tGdTdqfFUTPmWM6rXXG0nsoNicuVZ X-Google-Smtp-Source: APiQypJ/aBdeU79bhds1BhqB++aZepFlLO0GV7XK7BbW0ucZ2UOQn82nzsacMGOs1UAvsRPDWSQFUKaIF5V1wYz1iTg= X-Received: by 2002:a05:6e02:dcf:: with SMTP id l15mr2631052ilj.225.1588261352687; Thu, 30 Apr 2020 08:42:32 -0700 (PDT) MIME-Version: 1.0 References: <CABAhh3GKb8+zMpZRYEMeZ2c3J=ztXbXsZmsp9oVVPdS4LN=Sdg@mail.gmail.com> <CAPyj-LAjmiEPVwQbMnnT1xT+xOdSbWUzExyKN4cBmicHcyBjdg@mail.gmail.com> In-Reply-To: <CAPyj-LAjmiEPVwQbMnnT1xT+xOdSbWUzExyKN4cBmicHcyBjdg@mail.gmail.com> Date: Thu, 30 Apr 2020 16:42:20 +0100 Message-ID: <CALKiJKopmg=Y+inBvhgf--UwJKX2fXEq0xgBZYjUPtS557wsLQ@mail.gmail.com> To: php internals <internals@lists.php.net> Content-Type: multipart/alternative; boundary="000000000000bcd00105a483e9cc" Subject: Re: [PHP-DEV] [VOTE] match expression From: rowan.collins@gmail.com (Rowan Tommins) --000000000000bcd00105a483e9cc Content-Type: text/plain; charset="UTF-8" On Thu, 30 Apr 2020 at 13:18, Ilija Tovilo <tovilo.ilija@gmail.com> wrote: > There are three potential use cases for language wide block expressions. > > 1. Match expressions > 2. Arrow functions > 3. Everything else > > The problem is that they all have slightly different semantics. > [...] > I don't think that's actually true. If I'm understanding you right, you're concerned about two things: * Blocks which don't have a return value where one is expected / required. * Blocks which do have a return value where one is not expected. The language already has an established convention for both cases: a function with no return statement evaluates to NULL in expression context, and a function with a return value can be used in statement context and the result discarded. I see no immediate reason block expressions couldn't use the same rule. > $y = match ($x) { > 1 => {}, // Error, this does require a return value > }; > This could evaluate the block to null, and thus be equivalent to: $y = match ($x) { 1 => null, }; $x = fn() => {}; // This is fine, the function returns null > $x = fn(): ?int => {}; // Uncaught TypeError: Return value of > {closure}() must be of the type int or null, none returned > I had no idea that was an error; I guess it's the counterpart to ": void" - a style check rather than an actual return type check. But I don't see a particular problem with a short closure giving the same error as the equivalent named function (function foo(): ?int {}) so there doesn't seem to be anything extra to define here. > $x = fn() => { > foo(); > bar(); > <= baz(); // Why should we allow this? You can just use return > }; > Because right now, you *can't* use return; there are no block bodied short closures. If we did allow "return" here, there's no *fundamental* reason not to also allow it in a match expression, meaning "return this as the value of the match expression" (we might not *want* to reuse the keyword, but we *could*). > // All of these are errors, return value is required > $x = {}; > foo({}); > {} + 1; > // etc. > They would be evaluated as empty statements, and "return" null: $x = null; foo(null); null + 1; > It's also highly questionable whether use case 3 is actually very > useful at all because PHP doesn't have block scoping and all the inner > variables will leak out into the outer scope. [...] > An additional complication is that blocks already exist as "statement > list" statements > We could potentially solve both of these by introducing a new syntax which made something explicitly a block expression. I'm not sure what the keyword would be; "do" is already used, and "eval" has bad connotations, so I'll use "block" as a straw man to demonstrate. // block expression as RHS of assignment $this->foo = block { $bar = new Bar(); $foo = new Foo(); $foo->bar = $bar; return $foo; }; // $this->foo has been assigned, $bar and $foo are no longer in scope // block expression as arm of match expression $y = match ($x) { 1 => block { foo(); return bar(); }, } // if $x===1, foo() is executed, then $y gets the result of bar() // block expression as result of short closure $f = fn($x) => block { foo($x); bar($x); }; $f(); // even if the expression result isn't used, the scoping could apply if ( foo() ) block { $x = 1; }; // $x is not defined here // note trailing semi-colon, for the same reason you need one after a standard anonymous function definition // the above is actually equivalent to this: if ( foo() ) { block { $x = 1; }; } I don't know if I *like* this idea, but it would be a consistent language-wide implementation of the concept with minimal compatibility impact. It's not that black and white. I work in a lot of legacy projects that > could benefit from match expressions but it's simply not realistic to > refactor every single switch statement that contains more than a one > liner. > To use Larry's codenames, would those specifically benefit from "rustmatch" (evaluating the switch to an expression) or from "switchng" (a stricter switch statement)? I'd be interested to see a real-life example where you'd want both the match to evaluate to a value, and the arms to contain more than one statement. Regards, -- Rowan Tommins [IMSoP] --000000000000bcd00105a483e9cc--