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

Reply via email to