How can this Recursive lambda be invoked in Java?

I recently encountered this code in Java It involves functions and printing Fibonacci numbers, and how it works

public class AppLambdaSubstitution {

public static Function<Integer,Integer> Y(Function<Function<Integer,Integer>,Function<Integer,Integer>> f) {
    return x -> f.apply(Y(f)).apply(x);
}

public static void main(String[] args) {
    Function<Integer,Integer> fib = Y(
            func -> x -> {
        if (x < 2)
            return x;
        else
            return func.apply(x - 1) + func.apply(x - 2);
    });

    IntStream.range(1,11).
    mapToObj(Integer::valueOf).
    map(fib).forEach(System.out::println);
  }
}

The part that puzzles me is to return x – > F. apply (Y (f)) Applicable (x) Is y (f) a recursive call to the opposite method y? We always call it with function f as an argument For me, there is no basic case for this recursive call Why do endless recursive calls not overflow?

Solution

Basically, you missed the point of view of X – > f. Application (x) of apply (Y (f)); Instead of calling apply, it returns a function

This is just a very complex (and non intuitive?) To display IMO's currying and recursive functions It would be much easier to replace something and make it more readable

This structure:

Function<Function<Integer,Integer>>

No need at all, because the left parameter is not used at all You only need to master the right one So the parameter on the left can be anything (I'll replace it with a vendor later - no, but just to prove it)

In fact, what you care about here is this function, which performs actual calculations for each element of the stream:

public static Function<Integer,Integer> right() {

    return new Function<Integer,Integer>() {
        @Override
        public Integer apply(Integer x) {
            if (x < 2) {
                return x;
            } else {
                return apply(x - 1) + apply(x - 2);
            }
        }
    };
}

Now you can write the entire construct with the following:

supplier<Function<Integer,Integer>> toUse = () -> right();
 Function<Integer,Integer> fib = curry(toUse);
 IntStream.range(1,11)
          .mapToObj(Integer::valueOf)
          .map(fib)
          .forEach(System.out::println);

The supplier < function < integer, integer > > touse = () – > pair (); You should understand why the left part is needed in the previous example (function < function, function >) – just to get the right part

If you look closer, you may notice that there is no need for suppliers at all, so you can even further simplify it by:

IntStream.range(1,11)
         .mapToObj(Integer::valueOf)
         .map(right())
         .forEach(System.out::println);
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>