this should not refer to the lambda

Alex Blewitt alex.blewitt at gmail.com
Sun Feb 21 14:28:35 PST 2010


On 21 Feb 2010, at 21:50, Peter Levart wrote:

> On Sunday 21 February 2010 20:11:12 Alex Blewitt wrote:
>> 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.

Right, so this would be 'disallow recursive case' option.

> 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.

OK. That doesn't sound like a problem. After all, you can do those with arrays as well, right?

> Code statistics computed by some participants of this list show that you rarely 
> need that in anonymous inner SAMs today.

Rarely, but not never.

> 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).

Agreed. But you can still refer to members of the enclosing instance using an explicit qualified this, as I've noted.

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

I agree with you. But then, they don't make any sense on arrays either. 

Note also that regardless of what 'this' is implemented as - or even if it refers to a MethodHandle - it will still be possible to invoke those methods on the reference type.

#() foo = #() { };

foo.toString();
foo.wait(); //etc.

int[] bar = {1,2,3};
bar.toString();
bar.wait(); // etc

> 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.

No, because I doubt that the majority of usecases will use Object-level methods on the enclosing object. And for non-Object-level methods, you won't need to do this either. Arguably, a compiler warning of a self-reference to toString/equals etc. inside a lambda could be generated to warn in those cases where it's needed.

> 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.

Your example of inner classes - where people are ware of these things already - fits well into the model where the lambda is the 'this' as well. The programmer will be thinking in those same terms should 'this' refer to the lambda.

> They work that way, because they are classes. With known syntactic structure.

And there's no (good) reason here posted yet as to why an equivalent conceptual model cannot work for lambdas, regardless of their implementation.

> We can escape the metal jacket with them.

What exactly, is the metal jacket? I do not understand what kind of restrictions there are, or what cannot be done. Please enlighten me, because if there's something obvious I'm missing ... well, I'm missing it.

> 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.

It is just as arguable that using 'this' to refer to something other than its enclosing instance is inconsistent. The difference here is what the enclosing instance means. For a number of programmers used to inner classes, they may consider a lambda to work in the same way. But there is inconsistency in only permitting recursive lambdas by modifying the language structure such that in certain places, the LHS of an element can be defined with an assignment to a RHS which refers to the LHS.

Alex




More information about the lambda-dev mailing list