开发者

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. Tr开发者_JAVA技巧ace: 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)


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


ATOM is the predicate you are asking for.

I recommend using FLATTEN, a standard routine to flatten lists in lists - I present one implementation here.

(defun flatten (x)
  "descend into the supplied list until an atom is hit.
append the atom to the flattened rest"
  (if (endp x)
      x
    (if (atom (car x ))
    (append (list (car x)) (flatten (cdr x)))
      (append (flatten (car x)) (flatten (cdr x ))))))

Flatten returns a list: you can run LENGTH on the list to see how many ATOMS you wound up with.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜