Search code examples
algorithmcommon-lispclisp

Differentiate between a list and an atom in common lisp


I have a basic clisp function that I am making that just returns the number of atoms in a list. The issue I am having is I need it to increment for atoms in a list that is in the list, instead of seeing a list as 1 element in the list.

The real question I guess is how do you differentiate in your code whether an element is a list or an atom? If I can do that, I can send the lists to another function to add up and return the number of atoms they contain.

Clear as mud? :)

I have an example here:

(defun list_length (a)
  (cond ((null a) 0)
        (t (+ 1 (list_length (cdr a))))))

This works great if there are no embedded lists in the parent list, for example, '(1 2 3 (4 5) 6) would return 5. I need it to include 4 and 5 instead of the list (4 5) as one.

Thanks for your help.

Jon


EDIT:

(defun list_length (a)
  (cond ((null a) 0)
        ((listp (car a)) (list_length (car a)))
        (t (+ 1 (list_length (cdr a))))))

[18]> (list_length '(1 2 3 (4 5) 6))
1. Trace: (LIST_LENGTH '(1 2 3 (4 5) 6))
2. Trace: (LIST_LENGTH '(2 3 (4 5) 6))
3. Trace: (LIST_LENGTH '(3 (4 5) 6))
4. Trace: (LIST_LENGTH '((4 5) 6))
5. Trace: (LIST_LENGTH '(4 5))
6. Trace: (LIST_LENGTH '(5))
7. Trace: (LIST_LENGTH 'NIL)
7. Trace: LIST_LENGTH ==> 0
6. Trace: LIST_LENGTH ==> 1
5. Trace: LIST_LENGTH ==> 2
4. Trace: LIST_LENGTH ==> 2
3. Trace: LIST_LENGTH ==> 3
2. Trace: LIST_LENGTH ==> 4
1. Trace: LIST_LENGTH ==> 5
5
[19]> (dribble)

Solution

  • (listp foo) will return t if foo is a list and nil otherwise.

    So you can make your list_length function handle nested lists by adding the following case to your cond:

    ((listp (car a)) (+ (list_length (car a)) (list_length (cdr a))))