以函数式风格递归地遍历对象链
Walk a chain of objects recursively in functional style
命令式编码风格中的一个常见循环模式是跟随对象链找到结尾,例如:
private ThreadGroup rootOf(ThreadGroup leaf) {
ThreadGroup rootGroup = leaf;
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
return rootGroup;
}
(来自 this answer)
我觉得一定有一个标准的功能模式在逻辑上等同于此,但我不确定它是什么。我想出了下面使用 Vavr's Option
:
的递归方法
private ThreadGroup rootOf(ThreadGroup leaf) {
return Option.of(leaf.getParent()) // returns None for null
.map(this::rootOf)
.getOrElse(leaf);
}
但似乎应该有一种方法可以在没有显式递归的情况下做到这一点,尤其是在像 Java 这样没有尾调用优化的语言中(我在想象一些类似于 foldLeft()
但在迭代计算的价值流上,这是否有意义?)
这里的标准功能方法是什么?
Stream.iterate + 过滤应该做到:
Stream.iterate(leaf, ThreadGroup::getParent)
.filter(g -> g.getParent() == null)
.findFirst().get();
命令式编码风格中的一个常见循环模式是跟随对象链找到结尾,例如:
private ThreadGroup rootOf(ThreadGroup leaf) {
ThreadGroup rootGroup = leaf;
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
return rootGroup;
}
(来自 this answer)
我觉得一定有一个标准的功能模式在逻辑上等同于此,但我不确定它是什么。我想出了下面使用 Vavr's Option
:
private ThreadGroup rootOf(ThreadGroup leaf) {
return Option.of(leaf.getParent()) // returns None for null
.map(this::rootOf)
.getOrElse(leaf);
}
但似乎应该有一种方法可以在没有显式递归的情况下做到这一点,尤其是在像 Java 这样没有尾调用优化的语言中(我在想象一些类似于 foldLeft()
但在迭代计算的价值流上,这是否有意义?)
这里的标准功能方法是什么?
Stream.iterate + 过滤应该做到:
Stream.iterate(leaf, ThreadGroup::getParent)
.filter(g -> g.getParent() == null)
.findFirst().get();