我是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)))
)
答案 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)))