On 29/10/2020 22:49, Benjamin Morel wrote:
On Tue, 6 Oct 2020 at 14:09, G. P. B. <george.bany...@gmail.com> wrote:

Actually there is a precedent in PHP where braces don't create a new scope:
     $a = 1;

     {
         $a++;
     }

     echo $a; // 2


This is true. Indeed, in general, scope in PHP is not to the nearest pair of braces - if statements and loops don't create a new scope - but it is, with very few exceptions, to the current function, with no automatic inheritance/capture from the outer scope.

The fact that arrow functions *don't* have braces makes them look less like a normal function, so it is less surprising that they capture from their surrounding scope. The fact that they are limited to a single expression also reinforces that they are intended for a specific use case, and are not intended as a replacement for all anonymous functions.



Let's put it into context, here is how one of my service methods looks like:

     return $connection->transactional(function() use ($authorId,
$activityId, $parentId, $comment) {

... and this is not the largest one. Let's see how it would look like with
this proposal:

     return $connection->transactional(fn() => {


Just to be clear, the major gain here is not replacing the 10 characters "function()" with the 7 characters "fn() =>", it is eliminating the list of captured variables. So you would get equally clean code with a "capture all" syntax, such as:

    return $connection->transactional(function() use(*) {

or Sara's suggestion from earlier today:

    return $connection->transactional(function() use($) {


If I've counted right, this takes your example from 46 characters down to 17; but more importantly, that 17 is fixed no matter how many extra variables you want to capture or how long you make their names.


And I'm not worried about scope leaking:
usually, the closure takes up most of my service method.


To me, this illustrates exactly why we should have an explicit "auto-capture" syntax, rather than extending arrow functions: this is a form you would use in specific situations where you know it's appropriate, *not* a general-purpose replacement for the existing syntax.

As well as being shorter than the current syntax, arrow functions would remind people of JavaScript, where it's considered best practice to use arrow functions as much as possible, because they have *better* scoping - in particular, they automatically bind "this", which PHP closures already do.

There are certainly use cases where automatic capture leads to more elegant code than explicit capture; but there are also plenty of cases where it makes code hard to follow, and leads to subtle bugs. That's why I would like the two syntaxes to feel like equal options to choose between.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to