Re: [RFC] Short Closures 2, aka auto-capture take 3

From: Date: Tue, 14 Jun 2022 14:28:21 +0000
Subject: Re: [RFC] Short Closures 2, aka auto-capture take 3
References: 1 2 3 4 5 6  Groups: php.internals 
Request: Send a blank email to internals+get-117944@lists.php.net to get a copy of this message
> On Jun 13, 2022, at 1:39 PM, Rowan Tommins <rowan.collins@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

« previous php.internals (#117944) next »