gpt4 book ai didi

java - Java 中的这段递归 lambda 调用是如何工作的

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:26:57 27 4
gpt4 key购买 nike

我最近在 Java 中看到了这段代码。它涉及函数和打印斐波那契数,并且有效。

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);
}
}

让我感到困惑的部分是 return x -> f.apply(Y(f)).apply(x);Y(f) 不是递归调用Y 方法吗?我们一直使用函数 f 作为参数调用它。对我来说,这个递归调用没有返回的基本情况。为什么无限递归调用没有溢出?

最佳答案

从根本上说,您忽略了 x -> f.apply(Y(f)).apply(x); 的要点不会调用apply ,它将return一个Function .

这只是一种非常复杂(而且不直观?)的方式来展示柯里化(Currying)和递归函数 IMO。如果您替换一些东西并使其更具可读性,事情会简单得多。

这个结构:

 Function<Function<Integer, Integer>, Function<Integer, Integer>>

根本不需要,因为左边的参数根本没有使用。只需要捕获正确的一个。因此 left参数可以是任何东西(稍后我将用 Supplier 替换它 - 这也不是必需的,只是为了证明一点)。

其实你关心的就是这个FunctionStream 的每个元素进行实际计算:

 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);
}
}
};
}

现在您可以编写整个结构:

 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);

Supplier<Function<Integer, Integer>> toUse = () -> right();应该让您理解为什么在前面的示例 ( Function<Function, Function> ) 中需要 left 部分 - 只是为了捕获 right一个。

如果仔细观察,您可能会注意到 Supplier 完全不需要,因此您甚至可以通过以下方式进一步简化它:

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

关于java - Java 中的这段递归 lambda 调用是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46356074/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com