Closures, too much or too little?
Reinier Zwitserloot
reinier at zwitserloot.com
Mon Nov 23 15:40:34 PST 2009
Mark, spec-wise, "turning final" is effectively equivalent to the compiler
desugaring your source code snippet to:
int count = 0;
final int count0;
count++;
count0 = count; //generated
Runnable r = #() {doSomethingWith(count0);};
I haven't done an exhaustive analysis, but it seems that, if such a
desugaring results in legal code (e.g. the DA/DU rules don't cause an error
on usage or assignment of count0), it boils down to the same thing. The key
is to switch over to count0 at the right time. Neither right before closure
usage, nor right after last mutation, will be suitable.
Presuming a simple spec and implementation for this feature is possible, I
like it. However, as far as these things go, this change doesn't seem to
have all that much impact on the concept of @Shared/public variables for
closures. It won't get rid of needing to mutate outer scope - plenty of
closures where the closure is run inline (some sort of withLock construct,
for example), and the closure needs to communicate a result back to the
outer scope. Neal's basic approach is not a bad idea, though the warning
should not be generated if the gist of the warning can't actually happen,
and the compiler can figure this out: So, that would mean, auto-final, and
probably this concept of turning final just in time for the closure as well.
A bonus here is that the static analysis of code to ascertain if lack of
@Shared warrants a warning/error can be deferred until JDK8 if there's time
pressure. It won't be backwards incompatible to stop generating frivolous
warnings.
--Reinier Zwitserloot
NB: Mark, does closures-dev know about auto-final and not generating
warning/error if there is no mutation after the closure is defined?
On Mon, Nov 23, 2009 at 9:36 PM, Mark Mahieu <markmahieu at googlemail.com>wrote:
> On 23 Nov 2009, at 19:37, tronicek at fit.cvut.cz wrote:
>
> >
> >> So for me, a more practical variation of "auto-finalization" would be
> that
> >> the variable only 'becomes' final at the point in the code where the
> >> closure appears.
> >
> > What you mean by "becoming final"? Do you propose to flush all the
> > (non-final) variables, which are used in the closure, to the shared
> memory
> > at the point where this closure is declared?
>
> More musing on than proposing, but I'm suggesting that it's common for the
> local variable to only initially want to be mutable, whilst I'm in the
> process of setting up its value. After that's done with, I'd currently need
> to assign it to a final variable if I want to use its value in an anonymous
> class, which is annoying, even though (in my 'common' example) I make no
> attempt to assign to it again in the method, nor in any anonymous class (or
> closure) that references it.
>
> So I'm wondering whether there's a sensible (and clear) rule which would
> allow the compiler to do that 'annoying part' for me when necessary, such
> that:
>
> int count = 0;
> count++; // ok, obviously
>
> // count 'becomes' final about here
> Runnable r = #() { doSomethingWith(count); }; // still ok, not trying to
> assign to it
>
> count++; // compiler error - "Can't assign to variable 'count' after use
> in closure blah blah"
>
>
> It's kinda like the "auto-finalization" that Josh referred to, but
> deferring the "finalization" part until it's actually needed ('needed' being
> highly subjective, admittedly).
>
> Dunno.
>
> Mark
>
>
>
More information about the coin-dev
mailing list