kau*_*kau 7 java recursion lambda fibonacci java-8
我最近在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);
}
}
Run Code Online (Sandbox Code Playgroud)
困惑的部分是return x -> f.apply(Y(f)).apply(x);.是不是Y(f)递归调用该方法Y?我们一直以函数f作为参数来调用它.对我来说,这种递归调用没有基本情况.为什么无休止的递归调用没有溢出?
从根本上说,你错过了x -> f.apply(Y(f)).apply(x);不会打电话的apply那一点,它会return是一个Function.
这只是一种非常复杂(并且非直观?)的方式来显示IMO的currying和递归函数.如果你要替换一些东西并使它更具可读性,事情就会简单得多.
这种结构:
Function<Function<Integer, Integer>, Function<Integer, Integer>>
Run Code Online (Sandbox Code Playgroud)
完全不需要,因为根本没有使用左参数.只需要掌握正确的一个.因此,left参数可以是任何东西(我稍后将替换它Supplier- 这也不需要,但只是为了证明一点).
实际上你在这里所关心的就是Function对每个元素进行实际计算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);
}
}
};
}
Run Code Online (Sandbox Code Playgroud)
现在你可以用以下内容编写整个构造:
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);
Run Code Online (Sandbox Code Playgroud)
这Supplier<Function<Integer, Integer>> toUse = () -> right();应该让你理解为什么在前面的例子中(Function<Function, Function>)需要左边部分 - 只是为了得到right一个.
如果你看看更接近,你可能注意到了,Supplier是完全没有必要,因此你甚至可以进一步简化它:
IntStream.range(1, 11)
.mapToObj(Integer::valueOf)
.map(right())
.forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
281 次 |
| 最近记录: |