On Tue, Dec 16, 2025 at 10:01 AM Larry Garfield <[email protected]> wrote:
> On Tue, Dec 16, 2025, at 5:25 AM, Deleu wrote: > > On Tue, Dec 16, 2025 at 5:10 AM Rowan Tommins [IMSoP] > > <[email protected]> wrote: > >> (Replying to a few of you in one go, I hope the formatting is clear) > >> > >> >>> we have changed the RFC to use => instead. So the new syntax is > >> >>> > >> >>> using (new CM() => $cVar) { > >> >>> // Do stuff here. > >> >>> } > >> >>> > >> >> > >> >> Going to be controversial here, but this is confusing, because it > operates > >> >> in the exact opposite of every other usage of => we have. > >> > > >> > I agree with Matthew. > >> > > >> > I think it makes more sense to reverse them, like this: > >> > > >> > using ($cVar => new CM()) { > >> > // Do stuff here. > >> > } > >> > >> > >> It took me a long time to figure out what you were both saying here, > because to me the direction of the arrow seems to consistently indicate > data flow: you call the function, and data comes out; you enter the > context, and a variable comes out. > >> > >> But I think I see it now: you're treating the context variable like an > array key, that is somehow "bound to" the result. Except that's not what's > happening, otherwise we could just use "=". > >> > >> > >> >I also agree with Matthew but the reversed proposed here looks very > very > >> >awkward to me. I think the most natural thing is the “as” but I may > have > >> >missed the discussion on why it had to be changed. > >> > > >> >Thinking of foreach ($array as $value), an item from the array (left) > is > >> >assigned to $value (right). > >> > >> > >> This is the way to read the "as" syntax, yes; as I've said in a few > places, a Context Manager is like an iterator that goes around once. > >> > >> > >> > That seems symmetrical to using (new Manager as > >> >$manager) where the instance (left) is assigned to the variable > (right). > >> > >> > >> This, however, is why it was changed: that is *not* what is happening. > The Context Manager is not assigned to the variable, it *produces a value* > which is assigned to the variable. > >> > >> Again, look at the foreach equivalence: you wouldn't write "foreach(new > MyIterator as $iterator)", because it's not the iterator that ends up in > the variable, it's the *items produced by* the iterator. > >> > >> So you have "foreach(new MyIterator as $item)" and "using(new > MyContextManager as $contextVar)". > >> > >> But evidently that is not obvious to readers. > > > > My conclusion here is exactly the opposite of yours because this > > explanation makes `as` even more symmetrical now. As you've mentioned > > `foreach(new MyIterator as $iterator)` is not how it works. An iterator > > *produces a value* that is assigned to the variable after `as`. > > Symmetrically, `using(new ContextManager as $context)` the > > ContextManager is also producing a value that is assigned to the > > variable after `as`. The only difference is in the keyword: foreach > > will loop, but using will not loop since ContextManager is not an > > iterator. > > > > I'm assuming this would also be a valid syntax: `using ($manager = new > > ContextManager as $context)` which gives us a shot at capturing the > > context manager. > > > > I wrote a little snippet to try and see (using GitHub Gist Syntax > > Highlighter) how some of the options would look like once IDE support / > > syntax highlighting is baked in: > > > > image.png > > > > Ultimately, people will take a quick reading in a Context Manager > > documentation and the parallels to explain how it works seems to be > > very well in place for `as`, imo. > > > > In the image above I tried adding `for using` because I was trying > > really hard to come up with a word that could replace `each` in > > `foreach` to make it even more symmetrical, but I could not find > > anything decent. > > > > - `for context(new ContextManager as $context)` > > This one reads well, but the fact its two words (and a long word for > > that matter) doesn't sit well. > > > > - `for with(new ContextManager as $context)` > > I'm not a native English speaker, but I think this doesn't read at all > > > > - `for one(new ContextManager as $context)` > > Kind of implies it works with iterators (similar to each), which is not > > exactly the case and the language has very little motivation to create > > an iterator that loops only once just to make this work. > > > > - `for using(new ContextManager as $context)` > > Similar thoughts as `for context`, the only difference that makes me > > like this one more is because `for context` doesn't sit well with `try > > context` while `for using` could go well with `try using`. > > > > In any case, the longer I sit with this the more I dislike `=>` for > this. > > > > In an array, `=>` is an assignment of key/value pairs. > > For foreach ($iterator as $key => $value), the => is a destructing > > instruction that aligns with how the array was originally assigned. > > For the arrow function, it's kind of implied in the name ARROW function > > that we would need a syntax in the lines of `fn () =>`. I don't think > > this relates well with arrays, but it works well to me because of how > > universal arrow functions are in Javascript. > > For match ($value), it reads as `WHEN ($value) MATCH '' THEN. The arrow > > here `=>` is the THEN. > > > > My conclusion is that `=>` is either a value placement (for arrays) or > > an instruction execution (for arrow function and match). As such, If => > > were to be incorporated into Context Managers, I think it would make > > much more sense like this: > > > > `using (new ContextManager as $context) => [single line expression]` > > where the arrow creates a symmetry with how arrow functions work. > > > First, yeesh, where were y'all 2 weeks ago? :-P > > Second, I find it fascinating that there's so many different > mutually-incompatible spins on what => means. As argued in the > short-functions and auto-capture-closure RFCs from a few years ago, => in > nearly all cases currently means "evaluates to." > > $arr = [ > 'a' => 'A", > 'b' => 'B', > ]; > > $arr['a'] // This "evaluates to" A > > match ($foo) { > 'a' => 'A', > 'b' => 'B', // The 'b' case "evaluates to" B > }; > > fn($foo) => 'bar'; // This function "evaluates to" bar > > foreach ($arr as $k => $v) {} > > The last is a little bit inconsistent, but can still be read as "$k, and > the thing that $k evaluates to." > This is not at all how I read it. "evaluates to" is an assignment, and assignments in PHP flow right to left. In the case of an array, if I access the "a" key above, I get the value "A". For your match example, if the match applies to "a", I get the value "A". For an arrow function, I get the callable with the return. In other words, the expression on the right is either evaluated or assigned to the thing on the left. With the proposed syntax, "using ($expression => $variable) { ... }", this reads backwards: the expression is now on the left, and is captured to the thing on the right. That's what I'm saying will be confusing. > > So given that, and as Rowan noted the context manager is *NOT* the context > variable: > > using ($cm evaluates to $cv) {} > > That's the meaning we're going for. > And again, that doesn't make sense from typical assignment rules. This is why the other proposal's syntax ("let ($var = expression)") is not having the same debate - the syntax is consistent with existing usage. It's also consistent with how other scripting languages handle block scoping of variables (see JS, shell scripting). > > If there's some better word than =>, we're still open to it, but I am > going to insist on left-to-right reading. $cm is created first, then it > produces $cv. > > 'as' is what we had originally, since that's what Python used. However, > it was pointed out that it was confusing as it implied the CM and CV were > the same thing, or rather the expression on the left gets assigned to $cv, > which is not the case. Hence the change. > I didn't find it ambiguous, but I can see where others might. That said, I found it _less_ ambiguous than => here. > > A symbol does have the (dis?)advantage of a somewhat squishier meaning > than a keyword. > > I want block scoping; I have been bitten by accidental re-assignment within a block many times, and hate having to come up with an ever-so-slightly-different variable name to disambiguate. I don't care if it's this proposal or the "let" proposal in terms of how the engine handles it - but the syntax of "using (expression => $var)" isn't going to get my vote due to how easily it can be written incorrectly. I have no problem with the "using (expression as $var)" syntax, and the "let($var = expression) syntax is just fine for me as well. -- Matthew Weier O'Phinney [email protected] https://mwop.net/ he/him
