2014-02-19 51 views
0

我正在學習Lisp,我必須編寫一個函數,它的返回值是一個包含來自給定輸入的奇數整數(如果有的話)的列表。在代碼中我有這樣的:在Lisp中使用cons函數的問題?

(defun f3 (a) 
    (cond 
    ((null a) nil) 
    ((and (numberp (car a)) (oddp (car a))) (cons (car a) (f3 (cdr a)))) 
    (T (f3 (cdr a))) 
    ) ; end cond 
) 

我原本想使用append函數,但是我不斷收到錯誤。

向我推薦使用cons功能。當我這樣做時,我的功能開始工作(代碼在上面)。我原本是這樣的:

(defun f3 (a) 
    (cond 
     ((null a)()) 
     ((and (numberp (car a)) (oddp (car a))) (append (f3 (cdr a)) (car a)))) 
     (T (append() (f3 (cdr a)))) 
    ) 
) 

但不斷出現錯誤。例如,如果我調用(f3 '(1 2 3)),它會說「錯誤3不是類型LIST」。所以,我的問題是爲什麼cons在這裏工作,爲什麼append不起作用?缺點是如何工作的?提前致謝。

回答

6

append想要列表參數,(car a)不是列表。而不是(car a)你需要(list (car a))。換句話說,(append (f3 (cdr a)) (list (car a)))

這將基本上工作,但你會得到相反的結果。所以那應該是(append (list (car a)) (f3 (cdr a)))

另請注意,您的(append() (f3 (cdr a)))相當於(f3 (cdr a))

在原始產生的變化將是:

(defun f3 (a) 
    (cond 
     ((null a)()) 
     ((and (numberp (car a)) (oddp (car a))) 
      (append (list (car a)) (f3 (cdr a))))) 
     (T (f3 (cdr a))))) 

但是,你通常不會使用append到一個單一的元素,預先準備一個名單。更自然地使用cons來完成。

(cons (car a) (f3 (cdr a))) 

並最終把你的權利,你表現出工作版本:那麼

(append (list (car a)) (f3 (cdr a))) 

被更多適當地進行。

+0

正是我在找的東西。這是一個寫得很好的答案。 –

5

雖然像mbratch's answer將幫助你瞭解列表操作(因此可能是在您的研究這點你一個更加有用的答案),這一點也很重要,瞭解語言的標準庫,你正在使用。在這種情況下,您試圖過濾除奇數之外的所有內容。使用remove-if-not,這只是:

(defun keep-odd-numbers (list) 
    (remove-if-not (lambda (x) 
        (and (numberp x) (oddp x))) 
       list)) 
CL-USER> (keep-odd-numbers '(1 a 2 b 3 c 4 d 5 e)) 
;=> (1 3 5) 
+0

這非常有幫助。謝謝! –

+0

明確的喬什(+1)。事實上,我在贊成解釋所提出的解決方案時贊成最佳解決方案。 – lurker

1

雖然這不是一個修復你的實際問題,這@mbratch提供,這裏是我會用LOOP宏實現這樣的方式(另一部分標準庫):

(defun keep-odd-numbers (list) 
    (loop for x in list collecting x when (and (numberp x) (oddp x)))) 
+0

或者當(和(numberp x)(oddp x))收集x'('loop'非常靈活:))。 –