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

时间:2016-05-18 09:22:37

标签: lisp stack-overflow

我构建这个函数来检查是否所有" var"在名单上是数字。 这就是我试图做的事情

(defun check6 (list) 
(if  (null list) 'TRUE)
(if (not (numberp(first list))) nil)
(check6 (rest list)))

但总是让堆栈溢出。

为什么请?

3 个答案:

答案 0 :(得分: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

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

(defun check6 (list) 
  (if (null list)
      t
      (if (not (numberp (first list)))
          nil
          (check6 (rest list)))))

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

(defun check6 (list) 
  (cond ((null list) t)
        ((not (numberp (first list))) nil)
        (t (check6 (rest list)))))

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

(defun check6 (list)
  (loop for element in list always (numberp element)))

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

(defun check6 (list)
  (every #'numberp list))

答案 1 :(得分:0)

你一定要仔细看看Renzo编写函数的不同方法,但是你的代码可以通过早期从函数返回来修补:

(defun check6 (list) 
  (if (null list) (return-from check6 'TRUE))
  (if (not (numberp(first list))) (return-from check6 nil))
  (check6 (rest list)))

答案 2 :(得分:0)

你得到一个堆栈溢出,因为该函数永远不会终止。

Lisp中函数的结果是函数体中最后一个表达式的值 在你的情况下是(check6 (rest list))

我怀疑你正在考虑其他一些语言,这可能是用(用一种完全虚构的语言)写的:

bool check6(List list)
{
    if (list.empty())
        return true;
    if (!isNumber(list.head()))
        return false;
    return check6(list.tail());
}

但你的条件不会从函数返回结果;他们的结果只是因为你没有对它们做任何事情而被丢弃。

在上面的虚构语言中,您的功能将是

bool check6(List list)
{
    if (list.empty())
        true;
    if (!isNumber(list.head()))
        false;
    return check6(list.tail());
}

你可能会看到出了什么问题。

我个人发现与逻辑表达相比,难以遵循多管齐下的条件。

如果你写下列表是所有数字的条件:

  • 列表为空,或
    • 其头部是一个数字
    • 它的尾巴都是数字

直接翻译成Lisp:

(defun check6 (list)
  (or (null list)
      (and (numberp (first list))
           (check6 (rest list)))))

用虚构的语言,

bool check6(List list)
{
    return list.empty() || (isNumber(list.head()) && check6(list.tail()));
}

但是一旦你熟悉了高阶函数,你可能会写

(defun check6 (list)
  (every #'numberp list))

这可能是Lisp-y最多的解决方案。