this should not refer to the lambda

Peter Levart peter.levart at gmail.com
Sun Feb 21 13:50:36 PST 2010


On Sunday 21 February 2010 20:11:12 Alex Blewitt wrote:
> This prints out a countdown from n to 0:
> 
> #(i) { System.out.println(i); if(i>0) this.(i-1) };
> 
> So without 'this' referring to the enclosing lambda, you can't do
> this. An earlier proposal would be to have an illegal forward
> reference like:
> 
> countdown = #(i) { System.out.println(i); if(i>0) countdown.(i-1) }
> 
> So, you either allow 'this' as referring to the lambda (to support the
> recursive case), or disallow 'this' to refer to the lambda; at which
> point, you either disallow recursive cases or use hackery forward
> references to enable recursion.

#void(int) countdown = #(int i) { System.out.println(i); if(i>0) countdown.(i-1) }

...could be defined as a special function typed variable initializer (like for example array 
initializer). Plain and simple. No big deal.

> 
> Given that the example I posted earlier lets your refer to any number
> of nested lambdas, and that in the most case, the compiler should be
> smart enough to resolve the correct enclosing scope where necessary
> (i.e. you won't need to put 'this' in that frequently, since it will
> work up the stack to find it, much like inner classes work today) -
> what exactly is the problem with letting 'this' refer to the lambda?

There is an implicit "this" which is much more important than explicit "this".

If you make "this" refer to the lambda instance (of function type) and function types are 
reference types (subtypes of Object) then, to be consistent, you must treat unqualified Object 
members (hashCode, equals, wait*, notify*, getClass, toString) refer to the members of lambda 
instance too. Code statistics computed by some participants of this list show that you rarely 
need that in anonymous inner SAMs today. Quite the contrary, you often need to refer to 
Object members of enclosing instance. By making it necessary to qualify those references, you 
open the door to subtle bugs (some discovered just by inspecting the places in JDK sources where 
qualified "this" was used, see: http://mail.openjdk.java.net/pipermail/lambda-dev/2010-
February/000550.html).

I doubt that Object methods would have any utility being invoked on lambda instances:

- equals/hashCode (hm, very dangerous, since identity of lambda is unspecified)
- wait/notify (hm, very dangerous, since identity of lambda is unspecified)
- getClass (of no use - might allways be MethodHandle)
- toString (of no use either - might allways be the same)

On the contrary, they still have the same utility when invoked on an enclosing object instance. 
By forcing the programmer to qualify them (i.e. MyOuterClass.this.equals(...)) you have forced 
her to type more for the majority of usecases.

More importantly, NO programmer is qualifying references to other non-Object members of 
enclosing class (she is not a masochist is she?) when she's writing the body of a single method 
of an anonymous inner SAM instance. She's thinking in terms of outer class members at that time, 
so she must be very careful not to select any of the inner's Object methods by mistake.

> 
> The alternative seems to be to allow 'this' to refer to the lambda,
> and then use 'A.this' when you want to access the enclosing classes
> 'this'. I doubt many Java programmers would find that difficult,
> especially since that's how inner classes work today.

They work that way, because they are classes. With known syntactic structure. And yet anonymous 
inner instances of SAM interfaces would often be better of with "this" referring to enclosing 
class. This of course is not possible since it would be inconsistent with other 
anonymous/named/local/nested/top classes. Lambda expressions, on 
the other hand, are syntactically something entirely different. We can escape the metal jacket 
with them.

> 
> I have yet to see a technical argument of what can be done if you
> disallow 'this' as a lambda reference, other than having to type in
> n+1 extra characters should you ever want to refer to the enclosing
> scope.

I think I showed that "this" referring to lambda instance has a miniscule usage compared to the 
usage of implicit unqualified "this" (references to Object methods of enclosing instance).  
Tackling the problems of explicit "this" and implicit "this" (unqualified Object methods) 
separately - i.e. making "this" refer to lambda instance but unqualified Object methods refer to 
enclosing class - would be a big mistake. It would simply be inconsistent.

Regards, Peter


More information about the lambda-dev mailing list