JDK-8300691 - final variables in for loop headers should accept updates

Kevin Bourrillion kevinb9n at gmail.com
Wed Dec 11 22:36:44 UTC 2024


[note: I'm a new Oracle/JPG member, though this is coming from my personal
mail. I'm not speaking for the team though, just myself.]

Thanks very much for all your work on this, and your whole approach to it
all.

It is pretty easy to classify this as a "quality-of-life" improvement, and
I recall that it was very well-received on reddit. Since its main effect is
to let something work that otherwise would not work, and would force
busywork on the poor user, I think we'd be unlikely to get complaints about
it!

That said, I'd like to try to summarize the best argument against the
change (that I know of) anyway. To be clear, I don't think the team
currently views this argument as outweighing the benefits, but I wanted to
put it out there in case it sparks any further realizations out there. I
also apologize that it's not short!

A little background first:

What exactly gets captured when a lambda captures something? It has always
been of a *value*, never a whole variable. However, there's a trick,
because there is an invisible `this.` in front of any *field* mentioned,
and it is *that* value that is captured. This creates the illusion that
maybe it really is a variable being captured. So, to the user it might feel
like there are two different rules in effect for two different kinds of
variables.

Fortunately, the protections against capturing a non-effectively-final
local variable prevent that distinction from mattering! So users don't have
to be troubled by this quirk.

The enhanced for loop steps right up to the edge of this line. It seems
like *one* variable that is changing, right? But our allowing it to be
marked `final` is a statement that no, it really is a fresh variable each
time through the loop. And I claim that was sensible: there is nothing you
can do to that variable inside your loop body that has any chance of
affecting its value on the next trip through the loop. So it is *cleaner* to
conceptualize this as a new variable every time (as if its declaration had
been inside the braces).

All that is *not* the case for the classic for loop. Since the update
clause in the header is very often (usually!) an increment statement, your
changes in the body can certainly affect the next iteration. Obviously your
proposal excludes this case, as it must, but I claim that the *general* fact
remains: that to understand classic for loops we must be mindful that it
really is just one reused variable we're looking at.

None of this actually sinks your proposal by itself! But it does mean that
I would characterize your proposal as creating a special case: we feel it's
okay to allow it because we find it sufficiently *implausible* that the
user meant to capture the variable.

My concern is that now there will be some code out there that *appears* to
proclaim to the reader "hey, it's values, not variables, that get
captured". (Ironically, *it is!*, ha ha, so you'd think this is fine. But
as discussed a moment ago, the point is that today it's a "distinction
without a difference" and it wouldn't be anymore.)

I do fully get that not being able to refer to a loop variable in a lambda
is plain annoying. The next time I hit this in my own coding I will feel as
annoyed as anyone. :-) For what it's worth I see it as "just annoyance",
though, which has only a self-contained incremental cost each time you hit
it. I find it easy to accept costs like that, compared to the more
unknowable costs of opening up cracks in the user's clean and simple
conceptual model of how the language works (but that's me and my nature).

And I think that a reasonable reaction to that annoyance is "oh, right,
this is annoying, but at least it makes sense: this *is* a mutating
variable, and Java doesn't allow those across the board because they create
ambiguity." It at least doesn't teach a wrong lesson.

[Aside from all that, the second issue has been "are we sure this is really
the *one* exception to the usual rule that we need, and then we're done?",
but I don't have anything new to say about that.]

Having spelled that out, it is only for everyone's consideration. If the
benefits are considered to outweigh it, then we should go ahead and I'll
still be a happy camper.



On Wed, Dec 11, 2024 at 12:25 PM Archie Cobbs <archie.cobbs at gmail.com>
wrote:

> Dear Spec Experts,
>
> There is a (small) language change under consideration on amber-dev, and
> opinions have been expressed in multiple directions, so I'm turning to this
> list for hopefully some authoritative adjudication.
>
> The idea is: allow loop variables declared in basic (old style) for()
> loops to be captured in the body of the loop as long as they are not
> reassigned in the body of the loop, even though they might be reassigned in
> the loop step:
>
> for (int i = 1; i <= 3; i++) {
>     Runnable r = () -> System.out.println(i);   // allow this
> }
>
> Long discussion starts here (continues into October):
> https://mail.openjdk.org/pipermail/amber-dev/2024-September/008921.html
>
> Here's what has been drafted so far (all subject to improvement of course):
>
> Bug: https://bugs.openjdk.org/browse/JDK-8341782
> CSR: https://bugs.openjdk.org/browse/JDK-8341783
> JEP: https://bugs.openjdk.org/browse/JDK-8341785
> JLS: https://bugs.openjdk.org/browse/JDK-8341786
> PR: https://github.com/openjdk/jdk/pull/21415
>
> Just to be clear, I know it looks like I've got a lot personally invested
> in this, but honestly I don't care about the outcome. Yes I think this
> would be a nice tweak, but it's not my decision. Instead, the items listed
> above are there to create a tangible basis for making such a decision. I am
> really just trying to knock this item off my to-do list one way or the
> other (scrubbing the to-do list is a favorite year-end activity).
>
> Let me know your collective thoughts, ideally one of: ▢ Proceed ▢ Reject ▢
> Shelve it for later
>
> Thanks!
> -Archie
>
> --
> Archie L. Cobbs
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20241211/576005ac/attachment.htm>


More information about the amber-spec-experts mailing list