从列表中递归获取最小数量

时间:2012-02-17 21:09:07

标签: recursion lisp common-lisp

我是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作为答案,但如果还有其他方法,特别是不制作新功能,我欢迎。

这是我选择的答案所激发的最简单的代码。

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

3 个答案:

答案 0 :(得分: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 :(得分:2)

比较两个数字时,您需要以某种方式处理nil个案。这很容易做到。定义您自己的min版本,以满足

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

并使用它。

答案 2 :(得分:1)

我能想到的最简单的方法是包装min

的应用程序
(defun min-or-nil (num-list) 
   (when num-list (apply #'min num-list)))