人们说,除了没有尾递归优化这个jvm的限制外,clojure的实现非常出色。
http://lambda-the-ultimate.org/node/2547
据说将TCO(尾调用优化)实现到Python中会牺牲:
- 堆栈跟踪转储,以及
- 调试规律性。
如果在jvm中实现TCO,是否也需要做出同样的牺牲?还需要牺牲其他东西吗?
人们说,除了没有尾递归优化这个jvm的限制外,clojure的实现非常出色。
http://lambda-the-ultimate.org/node/2547
据说将TCO(尾调用优化)实现到Python中会牺牲:
如果在jvm中实现TCO,是否也需要做出同样的牺牲?还需要牺牲其他东西吗?
虽然不同(因为il指令已经存在),但值得注意的是.Net 64位JIT团队必须付出额外的努力来尊重所有尾调用。
我特别提到以下评论:
当然,缺点是如果您需要调试或分析优化代码,请准备处理看起来少了几个框架的调用堆栈。
我认为JVM也很难避免这种情况。
考虑到在要求尾调用优化的情况下,JIT应该假定它是必需的以避免堆栈溢出,因此这不是可以在调试版本中关闭的东西。如果在有趣的部分之前崩溃,那么它们对于调试毫无用处。实际上,“优化”是一个永久性功能,并且会影响受其影响的堆栈跟踪。
值得指出的是,任何避免在执行程序员在概念上描述/理解为堆栈操作(例如调用函数)的操作时创建真正的堆栈帧的优化都会导致在调试/提供堆栈跟踪时呈现给用户的内容与实际情况不符。这是不可避免的,因为描述操作的代码与执行操作的状态机的机制越来越分离。通常情况下,实现尾调用优化(TCO)会防止您获得完整的堆栈跟踪。这是不可避免的,因为TCO的整个目的是避免创建额外的堆栈帧。
值得注意的是,Clojure还具有一种非堆栈消耗的“recur”功能,以解决当前JVM版本上的这个限制。
例如:
(defn triangle [n accumulator]
(if
(<= n 0)
accumulator
(recur (dec n) (+ n accumulator))))
(triangle 1000000 0)
=> 500000500000 (note stack does not explode here!)