Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursively check for atoms in a list

I am attempting to write a small recursive program that tests a list and returns t if every element is an atom. The problem I am having is that when the function receives an empty list, it returns t instead of the desired result of nil. I cannot come up with a way to have it return nil for an initially empty list and still function properly in a recursive manner.

(defun only-atoms (in)
  (if (null in)
    t
    (and (atom (first in)) (only-atoms (cdr in)) )
  )
)
like image 244
Bort Avatar asked Oct 25 '22 14:10

Bort


2 Answers

The function can be implemented without recursion using e.g. every, as in:

(defun only-atoms (list)
  (and list (every #'atom list)))

When it comes to your stated problem that the function returns T instead of the desired result of NIL when the function is called with an empty list:

  1. Your recursive implementation explicitly returns T if (null in) is true, which explains your finding. Simply change it to the desired value NIL. Consider changing the if construct to and.

  2. Only make the recursive call when the list has more than one item. A well placed test for (rest in) will do. Provide a true value instead of making the recursive call if the list is at its last item.

  3. Carefully locate the only-atoms call to ensure that the function can be tail-recursive.

For example:

    (defun only-atoms (list)
      (and list
          (atom (first list))
          (or (null (rest list))
              (only-atoms (rest list)))))
like image 154
Terje Norderhaug Avatar answered Oct 31 '22 11:10

Terje Norderhaug


Use COND, which allows you to test for several cases:

  • empty list -> nil
  • one element list -> atom? ; hint: don't use LENGTH
  • else -> atom? for first element and recursive call for rest elements
like image 22
Rainer Joswig Avatar answered Oct 31 '22 09:10

Rainer Joswig