2013-09-22 115 views
0

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

我试图做的递归函数将会是cons,carcdr的列表。随着我的尝试,我无法返回nil。我只能忽略非整数数据。例如,(add-1-all '(1 2 3 a))将在每个数字加1后返回(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

你的第一句话,

我不能想办法在列表中搜索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

关键是要使用一个辅助函数,并且该辅助函数在它递归时随它携带答案,以便在必要时随时丢弃整个答案。顺便说一句,这也将是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))))) 
+0

这是有道理的。有没有一种方法可以在没有帮助功能的情况下做到这一点? – user2803198

+0

你可以编写一个函数,它接受可变数量的参数,如果它有1个参数,就像'add-1-all';如果它有2个'add-1-all-helper',或者你可以写'如果你只是在担心污染你的命名空间,那么在add-1-all里面的'let'里面加上'1-all-helper'。 –

+0

@NeilForrester你忘了解答。此外,通过使用具有默认值的可选参数或标签,您可以不使用帮助器功能。 – uselpa