【发布时间】:2016-04-13 15:18:43
【问题描述】:
我的理解(可能不正确或不完整)是 惰性求值 可以提供 尾递归 的所有优点,并且做得更好。
如果是这样,是否意味着在惰性求值的上下文中不需要尾递归?
更新
具体看下面的例子:
(define (foo f a)
(if (number? a)
(* a a)
(lazy-map foo a)))
这个函数可以很容易地转换为尾递归函数。但是,如果是这样,我们将失去惰性求值的优势。
实际上,当输入是一个非常大的列表(或无限)时,这个非尾递归函数是否需要消耗很多堆栈?我不这么认为。那么,是否有充分的理由使用 尾递归 而不是 惰性求值?
【问题讨论】:
-
不太清楚你在问什么。惰性求值是一种求值策略(通常可以通过使用词法闭包在用户空间中实现),而尾递归只是某种递归调用。即使在那里,我假设您实际上是指尾调用消除/尾调用优化,它允许优化尾递归以在更少的空间中运行。这允许递归程序不消耗所有的堆栈空间。您能否提供任何您认为惰性评估将消除尾调用优化需求的示例,反之亦然?
-
即使存在惰性求值,您可能仍然需要急切地计算一些东西。在这种情况下,您将使用带有严格计算的累积参数的尾递归。当你懒惰地构建你的结果时,即使用懒惰的构造函数,保护递归是要走的路,将递归调用放在懒惰的数据构造函数后面。有关 Haskell 的答案,请参阅 stackoverflow.com/questions/13042353/…
-
暂停投票让我有点困惑。 OP 显然对递归和惰性感到困惑,但这就是问题的重点。她/他基于混淆提出了一个合理的问题。 “不清楚你在问什么”的唯一原因是 OP 还不明白。如果她/他理解,就没有问题了。正确的反应是解释他/她为什么感到困惑——消除误解。一些 cmets 会这样做;在我看来,它们是正确的答案。
-
@mars: '惰性求值是否比尾递归做得更好' - 这是什么意思?什么“更好的工作”?什么是“重要角色”?尾递归提供了哪些“优势”?缺点呢?这完全是模糊的。没有例子。没有细节。甚至不清楚这些概念是否相关。既然存在符号,为什么需要数字?我希望有一个更具体的问题,需要投入更多的工作。为什么 Lisp 被标记,因为它不使用惰性求值?为什么不用 Haskell,因为它使用惰性求值。
-
@Mars:'既然存在 B,为什么需要 A? A 能提供 B 的所有优点吗? A 比 B 做得更好吗? ...' 这是许多无用问题的模式,同时提供零上下文并且没有真正的编程问题。这是一个低质量的问题。
标签: haskell clojure functional-programming scheme lazy-evaluation