recursive lambda as a local variable

Zhong Yu zhong.j.yu at gmail.com
Thu Sep 12 07:47:27 PDT 2013


Yes, it is quite dangerous. See also this IntelliJ bug [1] which
naively convert any
    ()->expr.method()
to
    expr::method
If `expr` is just a final variable (definitely assigned), the
conversion is safe; otherwise the conversion have a good chance of
being incorrect.

I guess IDE/compiler can issue a warning if a method reference is
bound to a suspicious expression.

[1] http://youtrack.jetbrains.com/issue/IDEA-113339

Zhong Yu


On Thu, Sep 12, 2013 at 8:00 AM, Gernot Neppert <mcnepp02 at googlemail.com> wrote:
> The line
> Runnable r2 = this.r2::run;
>
> from you examples shows one thing clearly: Bound Method References (BMRs)
> are questionable at best, dangerous at worst.
> Some quirky things about BMRs:
>
> - The part left of the '::' can be an arbitrarily long expression that will
> be evaluated immediately, while the method invocation itself will be
> deferred until the corresponding SAM method is invoked. Thus, 'null' might
> by bound now and detected much later.
>
> - Due to the early binding/late execution issue, BMRs are confusingly
> different from their plain lambda counterparts: 'this.r2::run' is very
> different from '() -> this.r2.run()' because r2 might be assigned later.
>
> - BMRs will usually neither save much typing nor be better readable than a
> corresponding plain lambda expression.
>
> Note that all of the above points are _not true_ with regards to Unbound
> Method References, (e.g. String::valueOf or Pojo::getName), which I'd
> consider a very useful addition to the lambda universe!
>
> So, should we get rid of BMRs? ;-)
>
>
>
>
> 2013/9/11 Zhong Yu <zhong.j.yu at gmail.com>
>>
>> On Wed, Sep 11, 2013 at 12:36 PM, Dan Smith <daniel.smith at oracle.com>
>> wrote:
>> > I'm pretty sure that's just the way things work.
>>
>> > Fields can refer to themselves in their initializers;
>>
>>
>> With lambda it is more confusing
>>
>> public class Tmp
>> {
>>     Runnable r1 = ()->r1.run(); // ok
>>
>>     Runnable r2 = this.r2::run; // compiles... but
>> NullPointerException at runtime
>> }
>>
>> Zhong Yu
>>
>>
>>
>>
>> > local variables cannot.  (This is because fields always have a value
>> > (possibly null), while local variables can't be accessed before
>> > initialization.)
>> >
>> > You could try the same thing with an int:
>> >
>> > int i = i+1;
>> >
>> > —Dan
>> >
>> > On Sep 11, 2013, at 10:37 AM, Zhong Yu <zhong.j.yu at gmail.com> 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