Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:111995 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 91729 invoked from network); 4 Oct 2020 20:55:14 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 4 Oct 2020 20:55:14 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B65091804C0 for ; Sun, 4 Oct 2020 13:08:11 -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=-0.6 required=5.0 tests=BAYES_00,BODY_8BITS, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) (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 ; Sun, 4 Oct 2020 13:08:11 -0700 (PDT) Received: by mail-wm1-f42.google.com with SMTP id d4so6507986wmd.5 for ; Sun, 04 Oct 2020 13:08:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:references:from:message-id:date:user-agent:mime-version :in-reply-to:content-transfer-encoding:content-language; bh=WrcNwApprWGDHd15E0knjrgqdRmhcvkct3qVFFQnVjI=; b=db6069l8OXxY6bAI7G4LojFqEm9mAIJQ76HyggxL/9OzCrnuodWkZTJF7goGvhDm8Q UiyVgG4t0dDlRManFQbE1vG7NBFVxBhvdwQrn2iTNspFRSxQiwJg7Bn6v3mDWmEhMRRY oqNYfL38azuLeypEMUfOrDeF+jvFduWNm6ILItznjpK7+6obYoX/z8hGxZcPNl3rTyfe L+CT39w3g4N3LKVL5cRfLOc1bWLSJQx2qxFdOKgUvukdJrZ6Vv417JDJm/RKKiy3xR36 Xq3Sq7UgA+GxzR6Tpx/Xyi+lEM33bKCgX58JVv7ZA8qsPVKg2OniyxfpwXkgaLPGSytL Er3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding :content-language; bh=WrcNwApprWGDHd15E0knjrgqdRmhcvkct3qVFFQnVjI=; b=nS2MOcNdOhYy9u/0JY4p6iVw+/xGLVNLl/Qg6FcuzmHTcyaLTg81gtB+GjW3zloGqO ux2TzldtBMgwkYGPkblFhoiratuobSVon1ALBq512z9ItDfBMZ8f2s8EUv3S0hDW+FGi uKBS8Z36cx40FHEqwSz+gPAgTE7tLZfe22ng8mPyleqMe+58N+FuWoN0gy4ftWnh6Ji7 xbG/ykBfKHSKWRFu/zZlPozEcFjW3vmOseHYbxT76jbrUvOMjDtYBFYqlqAF4r+0jsBH 32P2E+5ctLnjrz8RH0TosE49IRB70HxDazCdmucahusfme4x5H68SNTKO6wvj5a4EKzA 3vjA== X-Gm-Message-State: AOAM532ucyDyc1oXGuN5BDQIlRjPNtGpS0K9W/rCIMaq8ZstSaUJO7Y7 BRcojHP3ag4aZi0hwOcexr2OSr/jU0Q= X-Google-Smtp-Source: ABdhPJzFrSaBAiPz3QjVs1FK+QCSRpIWvRxxYvG6wJFWVN04e9R0M3pK5y2niMNeaHCtQz5ZTDxa7A== X-Received: by 2002:a1c:f208:: with SMTP id s8mr13646259wmc.85.1601842088791; Sun, 04 Oct 2020 13:08:08 -0700 (PDT) Received: from [192.168.0.22] (cpc104104-brig22-2-0-cust548.3-3.cable.virginm.net. [82.10.58.37]) by smtp.googlemail.com with ESMTPSA id n2sm3159311wrt.82.2020.10.04.13.08.07 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 04 Oct 2020 13:08:08 -0700 (PDT) To: internals@lists.php.net References: Message-ID: <446c9894-191f-e53b-4534-31c4e7b91d7b@gmail.com> Date: Sun, 4 Oct 2020 21:08:07 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.12.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-GB Subject: Re: [PHP-DEV] RFC: Support for multi-line arrow functions From: rowan.collins@gmail.com (Rowan Tommins) Hi Nuno, On 03/10/2020 22:09, Nuno Maduro wrote: > A few days ago I opened a pull request that adds support for multi-line > arrow functions in PHP: https://github.com/php/php-src/pull/6246. Welcome to the list. Firstly, it's probably worth having a look in the mailing list archives for prior discussions on this, as it was definitely discussed during the earlier short closures RFCs (the successful one that gave us fn()=>expr, and a couple of earlier attempts with different syntax and features). Secondly, I'd like to point out that "short closures" actually have three fundamental features: 1. They have an implicit "return", making them ideal for single expressions rather than blocks of procedural code. 2. They automatically capture all variables in scope, rather than having to import them with "use". 3. They are shorter than normal closure declarations, both because of the above two features, and because "fn" is slightly shorter than "function". I think it's worth making clear which of those three features we are hoping to retain by combining arrow functions with blocks. Feature 1 doesn't extend to code blocks in an obvious way. In some languages, every statement is a valid expression, so you can place an implicit "return" before the last statement of a block. In PHP, that's not the case, so e.g. { $x = 'Hello World; echo $x; } cannot be converted to { $x = 'Hello World; return echo $x; }. Alternatives include converting to { $x = 'Hello World; echo $x; return null; } or requiring all closure blocks to end with a valid expression. Feature 2 is probably the one most people actually want extended, but in my opinion is also the part most in need of justification, because it changes the language quite fundamentally. There are currently very few places in PHP where the scope of a variable is not to the current function: properties of the current object must be accessed via $this, and class properties via self:: or similar; globals must be imported via a "global" statement, statics via a "static" statement, and closed-over values via the "use" keyword. (The main exception to this rule is the half-dozen built-in "superglobals"; I think there are a few more obscure cases.) In a single-expression closure, as currently allowed, there is limited possibility for ambiguous scope. Extending this to function bodies of any size leads to much more risk of complexity and confusion. If you want to capture variables $a, $b, and $c, but have local variables $x, $y, and $z, you would currently write this: $f = function() use ($a, $b, $c) {     // $x, $y, $z must be local, because not imported } If we added an opt-in syntax for "capture everything", we might instead write this: $f = function() use (*) {      $x = $y = $z = null; } Without re-initialising all local variables, we would no longer be able to know if they were actually local without looking at the surrounding scope for a value that might be captured. I am unconvinced by this trade-off of opt-out instead of opt-in. One use case I've seen proposed is closures which capture a large number of variables; I would be interested to see an example where this is the case and is not a "code smell" in the same way as requiring a large number of parameters. In the above example I deliberately did not use the "fn()=>" syntax, because I believe this is really orthogonal to the other features - my impression is that actual expression length (feature 3 above) is more of a pleasant side-effect than a top priority for most people. I would personally prefer the "fn()=>" syntax to carry on meaning "this is an expression elevated to function status", and have some other syntax for a full closure that uses auto-capturing scope rules if that feature is indeed needed. Regards, -- Rowan Tommins (né Collins) [IMSoP]