> On Jun 13, 2022, at 1:39 PM, Rowan Tommins <rowan.coll...@gmail.com> wrote:
>
> On 13/06/2022 14:52, Larry Garfield wrote:
>>> That's one perspective. The other perspective is that the proposal is to
>>> extend closure syntax to support automatic capture.
>> As noted before, this is a distinction without a difference.
>
>
> It's a difference in focus which is very evident in some of the comments on
> this thread. For instance, Arnaud assumed that adding "use(*)" would require
> a change to arrow functions, whereas that never even occurred to me, because
> we're looking at the feature through a different lens.
>
>
>>> By the way, the current RFC implies you could write this:
>>>
>>> fn() use (&$myRef, $a) { $myRef = $a * $b; }
>> The RFC already covers that. $b will be auto-captured by value from scope
>> if it exists. See the "Explicit capture" section and its example.
>
>
> So it does. I find that extremely confusing; I think it would be clearer to
> error for that case, changing the proposal to:
>
> > Short Closures support explicit by-reference capture with the |use|
> > keyword. Combining a short closure with explicit by-value capture produces
> > an error.
>
> And the example to:
>
> $a = 1;
> fn () use (&$b) {
> return $a + $b; // $a is auto-captured by value
> // $b is explicitly captured by reference
> }
>
>
> Clearer syntax for this has been cited previously as an advantage of use(*)
> or use(...):
>
> $a = 1;
> function () use (&$b, ...) { // read as "use $b by reference, everything else
> by value"
> return $a + $b;
> }
>
>
>> 1. Auto-capture could still over-capture without people realizing it.
>> Whether this is actually an issue in practice (or would be) is hard to say
>> with certainty; I'm not sure if it's possible to make an educated guess
>> based on a top-1000 analysis, so we're all trying to predict the future.
>
>
> I tried to make very explicit what I was and was not disputing:
>
> > Whether the risk of these side effects is a big problem is up for debate,
> > but it's wrong to suggest they don't exist.
>
> The RFC seems to be implying that the implementation removes the side
> effects, but it does not, it is users paying attention to their code which
> will remove the side effects.
>
>
>> Arguably it's less of an issue only because short-closures are, well, short,
>> so less likely to reuse variables unintentionally.
>
>
> Our current short closures aren't just a single *statement*, they're a single
> *expression*, and that's a really significant difference, because it means to
> all intents and purposes *they have no local scope*. (You can create and use
> a local variable within one expression, but it requires the kind of twisted
> code that only happens in code golf.)
>
> If there are no local variables, there is nothing to be accidentally
> captured. That's why the current implementation doesn't bother optimising
> which variables it captures - it's pretty safe to assume that *all* variables
> in the expression are either parameters or captured.
>
>
>> 2. The syntactic indicator that "auto capture will happen". The RFC says
>> "fn". You're recommending "use(*)". However, changing the indicator syntax
>> would do nothing to improve point 1.
>
>
> The reason I think it would be better is because it is a more *intentional*
> syntax: the author of the code is more likely to think "I'm using an
> auto-capture closure, rather than an explicit-capture closure, what effect
> will that have?" and readers of the code are more likely to think "hm, this
> is using auto-capture, I wonder which variables are local, and which are
> captured?"
>
> Of course they can still guess wrong, but I don't think "fn" vs "function" is
> a strong enough clue.
"Strong enough" is an opinion, and it seems all who have commented have
differing ones of those.
But maybe a memory device would help address (some of?) your concerns:
- fn() — It is SHORT and implicit. Short is CONVENIENT. Thus Short
auto-captures variables because that is the most Convenient thing to do.
- function() — It is LONG. Long is more EXPLICIT. Thus Long requires Explicitly
declaring variables, which is also more rigorous and robust.
Or for the TL;DR crowd:
- fn() => SHORT => CONVENIENT => Auto-captures
- function() => LONG => EXPLICIT => Requires declaration
Hope this helps. #fwiw
-Mike
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php