Home > Software design >  Why is my lambda evaluated before the implementation is called?
Why is my lambda evaluated before the implementation is called?

Time:08-25

(credits: example from OCP Java 17 certification guide by Boyarsky and Selikoff)

To learn lambdas better, I put a breakpoint in the code (IntelliJ IDE) and started stepping through it.

Function<Integer, Integer> before = x -> x   1;
Function<Integer, Integer> after = x -> x * 2;
Function<Integer, Integer> combinedf = after.compose(before);
System.out.println(combinedf.apply(3));

I was surprised to find that the value for x has already been assigned.

1

When I step to the next line, it is again evaluated before the call to combinedf.apply()

I don't understand why.

2

I thought it might be due to compiler optimization and tried to fool it by not hardcoding the '3'.

Scanner scanner = new Scanner(System.in);
Function<Integer, Integer> before = x -> x   1;
Function<Integer, Integer> after = x -> x * 2;
Function<Integer, Integer> combinedf = after.compose(before);
System.out.println(combinedf.apply(scanner.nextInt()));

But I get the same result.

3

I followed @wuhoyt's suggestion and set breakpoint to All. I also split out the code. Now it shows as expected. I do not understand why the breakpoint must be set to All for it to work as expected.

Scanner scanner = new Scanner(System.in);
Function<Integer, Integer> before = x -> x   1;
Function<Integer, Integer> after = x -> x * 2;
Function<Integer, Integer> combinedf = after.compose(before);
Integer intput = scanner.nextInt();
Integer result = combinedf.apply(intput);
System.out.println(result);

CodePudding user response:

You can set 2 breakpoint on code where you create the function object.

Function<Integer, Integer> before = x -> x   1;

when I try to put breakpoint on this line, it tells me where I want to put, it give me 3 options

  1. Line
  2. x -> x 1
  3. All

I select "All", and I put another breakpoint on line

System.out.println(combinedf.apply(3));

And the debugging process goes from

Function<Integer, Integer> before = x -> x   1;   // create a function object
System.out.println(combinedf.apply(3));  // calling the apply method of the object
x -> x   1        // actual execution body of the function, this is where you put your break point, so the value of x is 3

In another word


Function<Integer, Integer> before = x -> x   1; 
// is equals
Function<Integer, Integer> before = new Function<Integer, Integer>() {
    @Override
    public Integer apply(Integer integer) {
        return integer   1;  // this is where somehow you put breakpoint, probably find out how this happened, 
    }
};

I am using IDEA2021 Community, it give me 3 option when I click left area of the line to put breakpoint

UPDATE

Why must I select "All" for breakpoint?

I guess you are asking why there are two places, and what are the differences?

Probably because laziness-init concept in functional programming. At first, the body won`t be executed, and when you finally call apply method(terminal operation), the body will be execute. Thus you can chain these functions or do other cool stuff with lambda expressions. There are at least two steps so you get two places to set breakpoint.

I found another answer here which is very good, be sure to check it out

https://stackoverflow.com/a/24542150/16702058

  • Related