【发布时间】:2016-08-21 17:42:34
【问题描述】:
我对跟踪/理解 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)
但我认为它很快就会变得太毛茸茸,是否有任何图片替代品或模态可以理解这一点?
【问题讨论】:
-
您所说的“因为在普通函数式语言中没有左参考上下文。”是什么意思?什么是“普通”函数式语言,函数在那里看起来如何?
-
@Bergi 我的意思是通常我会做
function foo(largerInstance) -> function foo(smallerInstance) .... function foo(baseCase),即我的函数调用仅取决于参数,但在这里我看到函数取决于调用函数的对象。 -
考虑一个对象,在该对象上调用函数作为始终存在的隐式参数(虽然并不总是使用,尤其是在 Scala 中)。喜欢
incl(union(union(left, right), other), elem)。只有所有函数的第一个参数都是多态的。 -
@CodeYogi 将对象视为第一个参数,属性被隐式解构/模式匹配等。
-
@VictorMoroz 很棒,但你不认为扩展这个函数会是一项痛苦的任务吗?在考虑递归算法时,你觉得这个函数或对象引用的哪个符号更有帮助?
标签: scala oop recursion recursive-datastructures