【问题标题】:Stack overflow regarding two functions关于两个函数的堆栈溢出
【发布时间】:2014-03-19 18:33:57
【问题描述】:

所以我是 lisp 的新手,我对我遇到的问题感到很困惑:

(defun factorial (x)
  (if (>= x 1)
      (* x (factorial (- x 1)))
      1))

阶乘函数可以输出3000!不过没问题

(defun sum (x)
  (if (<= x 1)
      1
      (+ x (sum (- x 1)))))

(sum 10000) 的堆栈溢出,我正在使用 clisp。

谁能解释一下为什么会这样?

【问题讨论】:

  • 不确定,但可能是语法错误 - sum 和 (- x 1) 之间应该有空格吗?
  • 会更漂亮,但这不是错误:/。我很不确定为什么会这样,难道是 lisp 有最大数量的递归调用吗?
  • 确实如此;如果您的解释器没有针对尾递归进行优化,那么您将拥有一个非常高的堆栈。你传递函数的数字是多少?这只是对阶乘的重新实现,对吧?
  • 是的,我在搞乱这样的基本功能,我通过 (factorial 5000) 和 (sum 5000) 工作正常,但是到 (sum 6000) 它不再工作并且它堆叠溢出,我该如何解决?
  • @jstaab 即使实现优化了尾调用,这些函数也不是以适用的方式编写的。每个堆栈帧都需要保持活动状态,直到递归调用返回,以便可以执行算术运算。 (一个非常聪明的编译器可能会想办法优化它,也许是 tail recursion modulo cons。)

标签: lisp clisp


【解决方案1】:

您的函数不是尾递归的,因此编译器(和解释器)会为每次迭代增加堆栈,最终用完它。

FAQ How do I avoid stack overflow? 中列举了您的选项;相关的是:

  1. 编译函数
  2. 增加 Lisp 堆栈大小
  3. 使用迭代而不是递归重写
  4. 使用尾递归重写并编译

【讨论】:

    猜你喜欢
    • 2017-10-20
    • 1970-01-01
    • 2019-05-18
    • 2020-08-20
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多