0

我想不出一种方法来搜索列表以确保它具有所有整数。nil如果有非整数数据,我想立即返回,如果没有,我想继续我的功能。

我试图制作的递归函数将conscar列表cdr的。通过我所做的尝试,我无法返回nil。我只能忽略非整数数据。例如,(add-1-all '(1 2 3 a))(2 3 4)在每个数字加一后返回。

    (defun add-1-all (L) 
            (if (null L) 
                L
              (if (integerp (car L))
                  (cons (+ (car L) 1) (add-1-all (cdr L)))
                  nil)))

我确实知道缺点正在发生这种情况,因为递归正在添加到列表中。

4

2 回答 2

4

你的第一句话,

我想不出一种在 Lisp 中搜索列表以确保它具有所有整数的方法。

听起来你想检查一个列表是否全是整数。您可以使用以下方法检查列表是否全为整数every

CL-USER> (every 'integerp '(1 2 3 4))
;=> T
CL-USER> (every 'integerp '(1 2 a 4))
;=> NIL

every将处理短路,即nil一旦发现第一个不符合谓词的元素就返回。

但是,您的代码听起来像是要在列表上进行映射,收集应用于每个整数的函数的值并返回收集的值,除非遇到非整数,否则返回 null。也许最简单的方法是使用loop宏。一个解决方案看起来几乎与英文规范相同:

CL-USER> (loop for x in '(1 2 3 4)
            if (not (integerp x)) return nil
            else collect (1+ x))

;=> (2 3 4 5)
CL-USER> (loop for x in '(1 2 a 4)
            if (not (integerp x)) return nil
            else collect (1+ x))

;=> NIL

与递归解决方案相比,这样做loop也有一些优势。虽然 Lisp 家族中的一些语言(例如 Schema)需要尾调用优化,并且一些 Common Lisp 实现也这样做,但 Common Lisp 中不需要。loop因此,如果您使用迭代解决方案(例如 with )而不是递归(甚至是尾递归)实现,它会更安全(例如,您不会耗尽堆栈空间) 。

于 2013-09-22T01:38:20.557 回答
1

关键是使用辅助函数,并且该辅助函数在递归时携带答案,以便它可以在必要时随时丢弃整个事情。顺便说一句,这也将是尾递归的,这意味着它可以处理极长的列表而不会耗尽堆栈空间。

(defun add-1-all (L) 
  (add-1-all-helper L nil))

(defun add-1-all-helper (L answer)
  (if (null L)
    answer
    (if (integerp (car L))
      (add-1-all-helper
        (cdr L)
        (cons (+ (car L) 1) answer)))))
于 2013-09-22T01:23:40.310 回答