我对跟踪/理解Javascript,Haskell等函数式语言中的递归调用感觉有点舒服,最近我在Scala学习课程,目前课程主要依赖于递归。
以下是一个简单的例子:
abstract class IntSet {
def incl(x: Int): IntSet
def contains(x: Int): Boolean
def union(other: IntSet): IntSet
}
class Empty extends IntSet {
def contains(x: Int): Boolean = false
def incl(x: Int): IntSet = new NonEmpty(x, new Empty, new Empty)
def union(other: IntSet): IntSet = other
}
class NonEmpty(elem: Int, left: IntSet, right: IntSet) extends IntSet {
def contains(x: Int): Boolean =
if (x < elem) left contains x
else if (x > elem) right contains x
else true
def incl(x: Int): IntSet =
if (x < elem) new NonEmpty(elem, left incl x, right)
else if (x > elem) new NonEmpty(elem, left, right incl x)
else this
def union(other: IntSet): IntSet =
((left union right) union other)incl(elem)
}
虽然直观的递归似乎是可以理解的,但是我很难扩展一般情况,而base case
感觉非常好。
((left union right) union other)incl(elem)
主要是因为左参考上下文在普通函数语言中不存在。如何在工作和理解这些递归调用时让自己舒服?
更新
基于我认为下面的答案将是扩展递归树的调用序列。
incl(union(union(left, right), other), elem)
incl(union(incl(union(union(left, right), other), elem), other), elem)
但是我觉得它很快就会变得毛茸茸,是否有任何图画替代或模式可以理解这一点?
答案 0 :(得分:0)
联盟是一个很难理解的方法,这是真的。当我第一次看到它时,它看起来很奇怪,看起来似乎做得很少。它确实有助于绘制出两棵小树并通过它来查看整个事物是如何工作的,但实质上,它与任何其他递归没有什么不同。大多数工作都是由incl
完成的,它实际上是将每个元素添加到int集中,一次一个。所有联盟都会一遍又一遍地递归地分解问题,直到你得到一个空的int集。然后逐个incl方法将每个元素添加回集合,将其构建为包含原始int集合和另一个int集合中的所有元素的集合。
奥德斯基的课程很棒。几个月前我自己完成了。