lisp -how检查所有列表是否都是数字

jor*_*dan 0 lisp stack-overflow

我构建这个函数来检查列表中的所有"var"是否都是数字.这是我试图做的

(defun check6 (list) 
(if  (null list) 'TRUE)
(if (not (numberp(first list))) nil)
(check6 (rest list)))
Run Code Online (Sandbox Code Playgroud)

但总是我得到堆栈溢出.

告诉我为什么?

Ren*_*nzo 10

堆栈溢出是由于您有几个不相关的事实if,因此它们生成一个未消耗的值并继续执行函数体的其余部分.这意味着check6永远不会终止并导致溢出.

如果将代码粘贴到适当的编辑器中(自动对齐代码行),您可能会发现编辑器产生了这种对齐:

(defun check6 (list) 
  (if (null list) 
      'TRUE)             ; only one branch, no else branch, continue to the next form
  (if (not (numberp(first list))) 
      nil)               ; again only one branch, continue to the next form
  (check6 (rest list)))  ; infinite loop
Run Code Online (Sandbox Code Playgroud)

如果你想使用if特殊运算符,你应该记住它有两种情况,当条件为真时和错误时,应该以这种方式嵌套表单(再次正确对齐):

(defun check6 (list) 
  (if (null list)
      t
      (if (not (numberp (first list)))
          nil
          (check6 (rest list)))))
Run Code Online (Sandbox Code Playgroud)

但Common Lisp具有更方便的连接条件语法,cond:

(defun check6 (list) 
  (cond ((null list) t)
        ((not (numberp (first list))) nil)
        (t (check6 (rest list)))))
Run Code Online (Sandbox Code Playgroud)

最后,请注意,通过使用迭代,还有其他方法可以解决您的问题:

(defun check6 (list)
  (loop for element in list always (numberp element)))
Run Code Online (Sandbox Code Playgroud)

或者以更简洁的方式使用高级功能:

(defun check6 (list)
  (every #'numberp list))
Run Code Online (Sandbox Code Playgroud)