我想不出一种搜索列表的方法,以确保它具有所有整数。如果有非整数数据,我想立即返回nil
,如果没有则继续我的功能。
我要尝试的递归函数将cons
car
与列表的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)))
我确实理解这种情况正在发生,因为递归正在添加到列表中。
答案 0 :(得分: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
)而不是递归(甚至是尾递归)实现,它可以更安全(例如,您将不会耗尽堆栈空间)。
答案 1 :(得分:1)
关键是使用辅助函数,并且该辅助函数在递归时随身携带答案,以便在必要时随时丢弃整个函数。顺便说一下,这也是tail recursive,这意味着它可以处理非常长的列表,而不会耗尽堆栈空间。
(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)))))