Common Lisp: Почему эта функция вызывает бесконечную рекурсию? - PullRequest
3 голосов
/ 29 октября 2011

Я пытаюсь написать функцию (lnn; list-not-nil), похожую на список, которая добавляет только значения, отличные от nil.

(list nil 3) --> (NIL 3)
(lnn nil 3) --> (3)

Вот код, который у меня есть. По какой-то причине это вызывает бесконечную рекурсию на любом входе, который я пытаюсь.

(defun lnn (&rest items)
  (lnn-helper nil items))

(defun lnn-helper (so-far items)
   (cond ((null items)
           so-far)
     ((null (car items))
      (lnn-helper so-far (cdr items)))
     (t (lnn-helper (append so-far (list (car items))) (cdr items)))))

Есть идеи? Большое спасибо.

Ответы [ 2 ]

4 голосов
/ 29 октября 2011
(defun lnn-helper (so-far &rest items)
  ...)

В этом списке аргументов items никогда не будет nil, если вы всегда вызываете lnn-helper с двумя аргументами.Удалите спецификатор &rest, и он будет работать.

2 голосов
/ 29 октября 2011

Ответ Матиаса должен был помочь.Также обратите внимание, что это просто простое сокращение:

(defun lnn (&rest elements)
  (reduce (lambda (elt acc) (if elt (cons elt acc) acc))
          elements
          :from-end t
          :initial-value nil))

Или даже (менее эффективно):

(defun lnn (&rest elements)
  (reduce #'cons (remove nil elements) :from-end t :initial-value nil))

Тогда:

(defun lnn (&rest elements)
  (remove nil elements))

:)

PS: я знаю, что это было, вероятно, просто упражнение по рекурсии, но SCNR.

...