recursive lambda as a local variable
Remi Forax
forax at univ-mlv.fr
Wed Sep 11 11:38:20 PDT 2013
On 09/11/2013 08:04 PM, Zhong Yu wrote:
> On Wed, Sep 11, 2013 at 12:54 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>> On 09/11/2013 07:32 PM, Zhong Yu wrote:
>>> State of the Lambda seems to suggest that this can be done for local variables:
>>>
>>> http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html
>>>
>>>> When a lambda expression appears in any other context, such as a return expression, there is no way for it to refer to itself. The proper approach in such cases is to name the object with a variable declaration and replace the original expression with a variable reference.
>> This can be done, everything can be done with a computer,
>> but it means initializing a lambda that capture a reference to itself.
>> So you may observe a state where the lambda is not fully initialized,
>> in between.
> but the lambda body can never be invoked before the lambda is fully
> initialized, correct? so it should be safe.
in general yes because you can not use an abstract class as functional
interface
and because all captured values are initialized before the reference on
the lambda
is published.
but if you have a self referenced lambda, either you have a problem because
the field that store the self referenced lambda is not final so it can
be seen
as uninitialized by another thread (on ARM by example) or you have to have
a dedicated implementation very specific for this case in the compiler
and in the JDK, that will not be able to evolve if we decide at some point
in the future to change the way class that embed a lambda are implemented.
FWIW, if you take a look to the history in the mercurial repository
you can find an implementation that support that case but has a serious
problem of publication :(
>
> in contract, the method body of an anonymous class could be invoked
> before the object is fully initialized.
Rémi
>
>> And you can also use a method reference instead of a lambda
>> static void run() {
>> run();
>> }
>> Runnable r = Foo:run;
>>
>> To summarize,this construct solves a corner case that is painful to
>> implement,
>> and hard to get right so it was rule out by the EG.
>>
>> Rémi
>>
>> On Wed, Sep 11, 2013 at 12:16 PM, Brian Goetz <brian.goetz at oracle.com>
>> wrote:
>>>> Its not so much "intentional" as a consequence of language rules that
>>>> predate lambda.
>>>>
>>>> In the first example, r is a field; in the second, it is a local. What the
>>>> first lambda really is shorthand for is:
>>>>
>>>> Runnable r = () -> this.r.run();
>>>>
>>>> So this lambda captures 'this', whereas the second lambda captures 'r'. The
>>>> latter runs into definite-assignment issues, but fields are not subject to
>>>> assignment and flow analysis.
>>>>
>>>> Of course, when you use 'this' from the initializer of a field, you are on
>>>> thin ice.
>>>>
>>>>
>>>> On 9/11/2013 12:37 PM, Zhong Yu wrote:
>>>>> This compiles: (b106)
>>>>>
>>>>> class Test
>>>>> {
>>>>> Runnable r = ()->r.run();
>>>>> }
>>>>>
>>>>> but this doesn't:
>>>>>
>>>>> void test()
>>>>> {
>>>>> Runnable r = ()->r.run();
>>>>> }
>>>>>
>>>>> is that intentional or a bug?
>>>>>
>>>>> Zhong Yu
>>>>>
>>
More information about the lambda-dev
mailing list