Why calling this function recursively does not throw a NullPointerException
Asked Answered
S

1

2

My question comes from this thread.

Consider this code:

public class Test {    
    static Function<Integer, Integer> fibLambda = null;
    public static void main (String[] args) { 
        fibLambda = n -> n <= 2 ? 1 : fibLambda.apply(n - 1) + fibLambda.apply(n - 2); 
        System.out.println(fibLambda.apply(6));
    }
}

The output above is 8.

What I don't get is that how fibLamdba is initialized? It seems that I totally miss how the method invocation is done because I though that this code would produce a NPE.

Hope my question is clear

Simoniac answered 4/1, 2015 at 20:7 Comment(6)
What does the first line of main say? fibLambda = . Why wouldn't it be set...?Dozy
I don't see why it SHOULD cause a NPE.Collado
@Dozy Yes, but it says fibLamdba = .. fibLambda.someFunction(..);Simoniac
Ohh. You've never seen a closure before, have you? It's a bit like that.Dozy
@Dozy Is this really a closure ? To me, a closure is a function that returns a function that depends on a parameter passed to the enclosing function.Sasha
@Dici: Yeah, it's not exactly a closure. But the idea that makes it work is quite similar. The value of fibLambda is the one that exists at call time.Dozy
M
6

Your code is equivalent to

static Function<Integer, Integer> fibLambda = null;

public static void main(String[] args) {
    fibLambda = n -> n <= 2 ? 1 : Example.fibLambda.apply(n - 1) + Example.fibLambda.apply(n - 2);
    System.out.println(fibLambda.apply(6));
}

By the time the apply is called fibLambda is assigned a value. Basically, the lambda expression doesn't capture the value of fibLambda, it just registers that the variable needs to be evaluated at the appropriate moment to produce a value.

Remember that a lambda expression doesn't execute the code appearing in its body. It's just a declaration, similar to how you declare an anonymous class instance.

Myxoma answered 4/1, 2015 at 20:9 Comment(4)
"Basically, the lambda expression doesn't capture the value of fibLambda, it just registers that the variable needs to be evaluated at the appropriate moment to produce a value." Thanks, now I understand. It was disturbing me now it's clear :)Simoniac
@Simoniac Just to be clear,t hat's because fibLambda is a class field. If it was a local variable, things would be different. It would be evaluated right away, and its value captured for use within the implementation.Myxoma
@SotiriosDelimanolis following your remark, I tried to make it local and found no way to do the same thing. Is this possible ?Sasha
@Sasha Not directly. That's what Jon Skeet's answer is trying to explain.Myxoma

© 2022 - 2024 — McMap. All rights reserved.