2013-09-22 45 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