this should not refer to the lambda
Alex Blewitt
alex.blewitt at gmail.com
Sun Feb 21 08:44:18 PST 2010
On 21 Feb 2010, at 15:26, Rémi Forax <forax at univ-mlv.fr> wrote:
> Just a last example: I don't want to explain why 'this' doesn't mean
> the same thing in the two codes:
>
> Object[] array = { this }; // here this doesn't refer to the array
>
> #Object() fun = #() (this); // here this refer to the lambda ??
This argument is somewhat tautologous. "I'd have difficulty in
explaining it because I don't like what it means".
>
Object o = new Runnable() { void run() { this;} }// this refers to the
runnable, not the enclosing object.
The # is a lot more like the Runnable than the block case; you are
(potentially) instantiating a new "thing" (it can throw OOM) and that
thing has reference semantics, much like an instance would. A block
cannot throw an OOM nor does it have reference semantics.
Note that I am not assuming any particular implementation of # but
these effects follow from the fact that # may be a closure over local
state (thus requiring a binding context to be created) and by virtue
that a lambda may be passed around as a reference.
Even if there is a third type of top-level element added to the
language, the it-doesn't-fit-my-mental-model-of-what-I'd-like-it-to-be
is not a good reason one way or another. What we have to ensure is
that we explain it in a way that people can conceptualise, and to
ensure that the # is treated as a psuedo-new operator to ensure that
it doesn't become a source of memory leaks.
(I use pseudo-new here because it shouldn't always create a new
instance, particularly when no local scope is captured.)
But having a potentially instance-creating, reference based type and
then disallowing the use of the operator in Java which is used to
refer to self-instances seems (to me) inconsistent with the language
as is (though of course, this is about changing the language).
And, as noted elsewhere, the ablility to reference the enclosing type
is not hindered in any way if "this" does refer to the lambda. As for
the nested lambda case, this is also possible (either implicitly due
to local state capture or explicitly) without having to resort to
language gymnastics like letting an RHS expression refer to the LHS
type.
public class A {
public class B {
public void foo() {
#() {
// Need to add this line if needed
Object me = this;
#() {
A.this; // A instance
B.this; // B instance
me; // outer lambda
this; // inner lambda
}
}
}
}
}
It seems this doesn't prevent anything and doesn't require self-refs
to be designed as:
Object me = #() { me}
There is no other construct in Jaca where you can do:
Object foo = ... foo ...
Since on the RHS foo isn't in scope. And it'll cause merry hell for
IDEs which are built to assume that the RHS can't refer to an LHS
assignment - a not unreasonable assumption in any language. (This may
also break refactoring concepts as well; whilst there will obviously
extensions which will be needed to treat lambdas in the general case,
the being able to refer to the LHS from the RHS is the primary issue.)
Still, I suppose we couldn't screw up more than generics, so if we do
allow RHS to use LHS then it will just be another future pain point
for Java programmers of the future.
Alex
More information about the lambda-dev
mailing list