<div dir="ltr"><div dir="ltr"><div dir="ltr">On Mon, Oct 21, 2024 at 8:13 PM John Rose <<a href="mailto:john.r.rose@oracle.com" target="_blank">john.r.rose@oracle.com</a>> wrote:</div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>


<div><div style="font-family:sans-serif"><div style="white-space:normal">
<p dir="auto">I think there might be something worth doing with some concept possibly denotable as “effectively frozen”, so I read quickly through much of this thread  but failed to find the definition of “frozen” per se (that is, explicitly, not effectively, frozen).  Lots of references with “you-know-what-I-mean” quotes, but I can’t tell what “frozen” is supposed to mean here.</p>
<p dir="auto">(I will thank anyone who points out the definition in this thread of “frozen”.  But I will plough forward with my own attempt…)</p></div></div></div></blockquote><div>My apologies for "effectively frozen", it was an off-the-cuff placeholder, but a poor one because as you point out "freezing" and "frozen" have their own (mostly unrelated) history.</div><div><br></div><div>Anyway, here's the definition we were using... maybe a better term would be "quiescent"? Let v be a variable, and let P be a character position in a source file. Then <i>v is </i>quiescent<i> at P</i> if there exists no position Q ≥ P at which there exists an assignment to, or mutation of, v.</div><div><br></div><div>Then a variable may be captured by a lambda at P only if it's quiescent at P. Note, locations Q ≥ P include the lambda itself so this enforces no mutations within the lambda.<br></div><div><br></div><div>The thought was that "quiescent" might be a candidate pragmatic answer (read: compromise that satisfies no one :) as it's easy to understand and would permit most capturing scenarios while still avoiding the most acute form of the ambiguity that "effectively final" was designed to avoid. As a data point, this change would allow elimination of 94% of the "dummy variables" in the JDK itself.<br></div><div><br></div><div>Re: "final shadowing - that is a nice concept - it aligns with the reality of what actually happens (usually a good thing).</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:sans-serif"><div style="white-space:normal"><p dir="auto">Along that slippery slope we quickly fall into the question of opening the floodgates, and doing final-shadowing on all lambdas everywhere....<br></p>
<p dir="auto">Why did’t we do this?  There are number of reasons, but the core design goal for capture (of up-level variables in both lambdas and inner classes) was to eliminate the opportunity to observe a divergence in the behavior of the original up-level variable, as opposed to the name which represents it in the lambda.</p></div></div></div></blockquote><div>This made me realize this issue really is all just about naming. For example, outer instances are captured just like variables, but we don't have a problem there because the captured version of the variable has a different name inside the nested class vs. outside (i.e., "Outer.this" vs. "outer", if you create the nested class via "outer.new Inner()").</div><div><br></div><div>So with a captured variable, we are using the same name for what are in reality two different things. But instead of saying "these are really two different things" we say "there is only one possible value this/these things could have no matter where you are and so you can just pretend there is only one thing".<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:sans-serif"><div style="white-space:normal">
<p dir="auto">This is obviously a good goal, since code is easier to read when the same name means the same thing everywhere, as opposed to “sometimes the live variable and sometimes a snapshot I already took”, which is what lambda snapshots give you.<br></p></div></div></div></blockquote><div>Entering personal opinion territory here... I wouldn't see such a big downside with allowing capture of any variable. Maybe that's just because I know how it really works? It's just a read-only snapshot taken at that point. Even if it were a new concept, that's just not a hard concept to grasp... especially in light of the many trickier Java topics like superclass constructors invoking subclass methods, mutual recursion between class initializers, anything to do with multi-threaded code...<br></div><div><br></div><div>To me the "effectively final" requirement is like a baby gate that you have to step over every time you walk between the kitchen and the dining room. It's not a huge obstacle or anything, but it makes you wonder, who are the toddlers we are trying to protect here? And haven't they all grown up by now? :)<br></div></div><div class="gmail_quote"><br></div><div class="gmail_quote">Now back to practical reality... I've drafted a <a href="https://bugs.openjdk.org/browse/JDK-8341785">fix</a> for basic for() loops & would be interested in your feedback.<br></div><div class="gmail_quote"><br></div><div class="gmail_quote">Thanks,<br></div><div class="gmail_quote">-Archie</div><div class="gmail_quote"><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature">Archie L. Cobbs<br></div></div>
</div>