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

Community
  • 1
  • 1
user2336315
  • 15,697
  • 10
  • 46
  • 64
  • What does the first line of `main` say? `fibLambda = `. Why wouldn't it be set...? – cHao Jan 04 '15 at 20:09
  • I don't see why it SHOULD cause a NPE. – MightyPork Jan 04 '15 at 20:09
  • @cHao Yes, but it says `fibLamdba = .. fibLambda.someFunction(..);` – user2336315 Jan 04 '15 at 20:10
  • Ohh. You've never seen a closure before, have you? It's a bit like that. – cHao Jan 04 '15 at 20:12
  • 1
    @cHao 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. – Dici Jan 04 '15 at 20:19
  • @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. – cHao Jan 04 '15 at 20:31

1 Answers1

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.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • 1
    _"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 :) – user2336315 Jan 04 '15 at 20:15
  • 2
    @user2336315 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. – Sotirios Delimanolis Jan 04 '15 at 20:17
  • @SotiriosDelimanolis following your remark, I tried to make it local and found no way to do the same thing. Is this possible ? – Dici Jan 04 '15 at 20:23
  • 2
    @Dici Not directly. That's what [Jon Skeet's answer](http://stackoverflow.com/a/27767874/438154) is trying to explain. – Sotirios Delimanolis Jan 04 '15 at 20:25