2012-02-17 25 views
1

我是lisp的新手,嘗試編寫一個遞歸函數,該函數返回列表中的最小數。它也想要檢測原子。下面的代碼返回錯誤:從列表中遞歸獲取最小數目

(defun minFromList (l)  
    (cond ((null l) nil) ; Causes error shown below 
; (cond ((null l)) ; Causes the same error 
; (cond ((null l) 0) ; It causes always 0 to be the final return val. 
     ((numberp l) l) 
    ((numberp (car l)) (min (car l) (minFromList(cdr l)))) 
    ((listp (car l)) (min (minFromList (car l)) (minFromList (cdr l)))) 
    (t nil)  ; if all condition doesn't hold just return nil. 
) 
) 

錯誤:

*** - MIN: NIL is not a real number 

顯然問題出在當給定列表爲空在那裏返回nil/0。什麼是可能的解決方法?謝謝。

環境)的Ubuntu 11.10,CLISP 2.49


更新)雖然我已經拿起this的答案,我歡迎,如果有其他的方法尤其是W/O如有作出新的功能。

下面是我選擇的答案所激發的最簡單的代碼。

(defun minNum (a b) 
    (cond ((null a) b) 
    ((null b) a) 
    (t (min a b))) 
) 

回答

2

當比較兩個數字,你需要處理nil情況下以某種方式。這很容易做到。定義你自己的min版本滿足

(min2 nil <x>) = <x> 
(min2 <x> nil) = <x> 
(min2 <x> <y>) = (min <x> <y>) if <x>, <y> non-null 

並使用它。

+0

我認爲你可以使用CLOS來實現這種風格。這是什麼語言? – 2012-02-18 00:20:32

+0

@claytontstanley我發佈的內容不是可執行代碼,只是一個規範。 :)但是,是的,CLOS讓您以這種方式指定'min2',雖然它很可能是矯枉過正相比,在這種情況下'cond'。如果你想在CL模式匹配(統一,甚至),不過,總是有[CL-UNIFICATION(http://common-lisp.net/project/cl-unification/)庫,它工作得很好。 – 2012-02-18 11:40:47

4

顯然你會得到一個錯誤信息,因爲你試圖使用你的函數的結果作爲一個數字,並說結果是nil當函數調用一個空列表作爲參數,所以試圖使用結果的評估失敗。這不是一個Common Lisp問題 - 當參數爲空時,您必須決定返回什麼。也許0是一個很好的值,也許是一些近似的負無窮大 - 只有你(或者使用你的函數的人)可以說明。對於獲得列表的最小值(或總和或任何其他'減少'),這是已由reduce Common Lisp標準函數處理的模式。所以min-from-list可能類似於:

CL-USER> (defun min-from-list (list &optional (default 0)) 
      (reduce #'min list :initial-value default)) 
MIN-FROM-LIST 
CL-USER> (min-from-list '(1 2 -3)) 
-3 
CL-USER> (min-from-list '(1 2 -3) -7) 
-7 
CL-USER> (min-from-list '()) 
0 
CL-USER> (min-from-list '() -3) 
-3 

(用戶可以指定哪些空列表的最小值是 - 如果沒有指定,這是0)。

1

我能想到的最簡單的方法是包裝的min的應用程序。

(defun min-or-nil (num-list) 
    (when num-list (apply #'min num-list)))