如何修复 Lisp 中的堆栈溢出错误

How to fix a stack overflow error in Lisp

我这里有一个代码,它试图获得低于给定数字的所有素数的总和。当我 运行 它时,我不断收到堆栈溢出错误,仅此而已,我似乎找不到哪里出错了。

(format t "Enter your number ~%")

;global variables
(defvar *number* (read))

(defvar *conditional-check* nil)

(defvar *prime* nil)



;sum-of-primes function 
(defun sum-of-primes (x)
    (defvar sum 0)
    (primeCheck x 2)
    (if (equal *prime* 'yes) 
        (progn
            (setf sum (+ sum x))
            (setf z (- x 1))
            (conditional z)
            (if (equal *conditional-check* 'yes) (sum-of-primes z) ()))
        (and (setf z (- x 1)) (sum-of-primes z)))
)


;conitional function
(defun conditional (z)
    (if (>= z 1) (setf *conditional-check* 'yes) (setf *conditional-check* 'no))
)


;prime number check
(defun primeCheck (*number* y)
    (if (and (>= *number* y) (not (= (mod *number* y) 0))) 
        (progn 
            (setf z (+ y 1))
            (primeCheck *number* z)
            (setf *prime* 'yes))
    (setf *prime* 'no))
)

;function call
(sum-of-primes *number*)


Whosebug 表示称为堆栈的内存部分已达到其限制。澄清一下,在堆栈上存储了函数调用。现在,如果存储函数调用的内存部分达到了它的限制,那就意味着发生了太多的函数调用。这通常意味着无限递归。想象一个只调用自身的函数。现在,如果您调用该函数,那么该调用将存储在堆栈中。但是,该函数调用自身,并且第二个调用也存储在堆栈中。而第二次调用是第三次调用该函数,入栈等。

递归的这种错误使用可以通过查看代码的特定区域来解决,在这些区域中函数本身被调用,或者更广泛地说,如果函数已经在堆栈中,但是又被调用了。

这是您需要的理解,以便找到解决当前问题的方法并避免将来出现类似问题。

sum-of-primes 缺少一些 基本条件 ,这会结束递归调用。这是主要问题,但是您的代码非常混乱并且包含许多无用的全局变量。您应该避免使用全局变量并使用局部变量(由 let 或函数调用创建)。对于这个例子,你根本不需要任何全局变量。

(defun sum-of-primes (num)
  (sum-of-primes-help 0 num))

(defun sum-of-primes-help (i num)
  (cond ((= i num) 0)
        ((primep i) (+ i (sum-of-primes-help (+ i 1) num)))
        (t (sum-of-primes-help (+ i 1) num))))
         
(defun primep (num)
    (primep-help 2 num))

(defun primep-help (i num)
  (cond ((= num 0) nil)
        ((= num 1) nil)
        ((= i num) t)
        ((= 0 (mod num i)) nil)
        (t (primep-help (+ i 1) num))))

(defun program ()
  (format t "Enter your number ~%")
  (format t "Sum of primes is: ~s" 
          (sum-of-primes (read))))

那你就打电话给(program).