3

I am trying to write a function (lnn; list-not-nil) similar to list that only appends values that are not nil.

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

Here is the code I have so far. For some reason it causes infinite recursion on any input that I try.

(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)))))

Any ideas? Thanks very much.

2 Answers 2

4
(defun lnn-helper (so-far &rest items)
  ...)

With this argument list, items will never be nil if you always call lnn-helper with two arguments. Remove the &rest specifier, and it'll work.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, I made this correction, but I still get infinite recursion.
@Miriam It works for me: (lnn nil 3) => (3); (lnn 1 2 nil 3) => (1 2 3). What input results in the infinite recursion?
I'd also be tempted to CONS the elements onto the head of SO-FAR, then finish by returning (NREVERSE SO-FAR), won't matter for short lists, but APPEND is O(n) so LNN-HELPER ends up being O(n^2).
2

Matthias' answer should have helped. Also note, that this is just a simple reduction:

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

Or even (less efficient):

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

Then:

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

:)

P.S.: I know this was probably just an exercise in recursion, but SCNR.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.