Получить минимальное количество рекурсивно из списка - PullRequest
1 голос
/ 18 февраля 2012

Я новичок в 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


Обновление) Хотя я уже подобрал этот в качестве ответа, я приветствую, если есть другие способыособенно без создания новых функций, если таковые имеются.

Вот самый простой код, который я сделал, вдохновленный выбранным ответом.

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

Ответы [ 3 ]

4 голосов
/ 18 февраля 2012

Очевидно, вы получаете сообщение об ошибке, потому что вы пытаетесь использовать результат вашей функции как число, и этот результат равен nil, когда функция вызывается с пустым списком в качестве аргумента, поэтому оценка, которая пытается использовать результат не получается. Это не проблема Common Lisp - вы должны решить, что возвращать, когда аргумент пуст. Возможно, 0 - это хорошее значение, может быть, какое-то приближение минус бесконечности - только вы (или тот, кто использует вашу функцию) может сказать.

Что касается получения минимума (или суммы, или любого другого «сокращения») списка, то это шаблон, уже обработанный стандартной функцией Common Lisp reduce. Так что 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).

2 голосов
/ 18 февраля 2012

При сравнении двух чисел вам нужно как-то разобраться со случаем nil.Это легко сделать.Определите свою собственную версию min, которая удовлетворяет

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

, и используйте ее.

1 голос
/ 18 февраля 2012

Самый простой подход, который я могу придумать, - это обернуть приложение в min.

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