#### Archived

This topic is now archived and is closed to further replies.

# Lisp: traversing a cons list

## Recommended Posts

master_ball    132
I''m playing around with Lisp and have made a global variable *database* that is a cons list. In it are structs of people. I''ve given them stats, such as name, sex, parents, children, strength, speed, and on and on. I can''t figure out how to traverse the list. Say I want to find all of the males in my database, or everyone with a speed of say 10, and print out the names. How would I go about this? I thought about doing it recursivly with cdr, but I can''t get it to work. Thanks! -- master_ball -- ------------------------------ We R 138

##### Share on other sites
Diodor    517

  (defun print-odd (l)  (if (null l)     nil     (progn        (when (oddp (car l))              (print (car l)))        (print-odd (cdr l)))))         (PRINT-ODD '(1 2 3 4 5))1 3 5 NIL

You can make a more general utility:

  (defun print-if (pred lst)    (if (null lst)        nil        (progn            (when (funcall pred (car lst))                    (print (car lst)))            (print-if pred (cdr lst)))))(PRINT-IF #'oddp '(1 2 3 4 5))1 3 5 NIL

But the best way is to use mapping functions. Look up mapl, mapc, mapcar, mapcan, mapcon, maplist.

  (defun print-if (pred lst)    (mapc #'(lambda (x)               (when (funcall pred x)                  (print x)))          lst))1 3 5 (1 2 3 4 5)

Or you can use the almighty loop:

  (defun print-if (pred lst)    (loop for it in lst do        (when (funcall pred it)             (print it))))

To collect all elements in a list of a certain property:

  (defun collect-if (pred lst)    (mapcan #'(lambda (x)                 (when (funcall pred x)                       (list x)))            lst))(COLLECT-IF #'oddp '(1 2 3 4 5))(1 3 5)

[edited by - Diodor on April 29, 2003 12:31:46 AM]

##### Share on other sites
bishop_pass    109
Think hard about the flexibility you have with regard to how you may arrange symbols in s-expressions which represent knowledge. Think also about the fact that in many cases you''re better off creating name-value pairs, such as (gender male) and (occupation farmer). In this way, you can have any number of different elements in your knowledge base, and missing ones as well.

Then look into assoc, or roll your own function.

The point of my post is that you have immense flexibility in how you choose to create and store data in Lisp.

##### Share on other sites
flangazor    516
I disagree in terms of style, bishop. I think that there should be a spec and a macro for printing the template of the person type. Then there should be push/pop/find/find-all accessors. I would also use a hash table for datasets greater than 20 (where on many lisp systems, hash becomes faster then assoc-list).

Maybe my mind has been corrupted by OOP but I think this is good because you can then keep the actual data small, and you can write the find, which makes find all quite easy. push and pop are almost trivial as well!

yum yum.

##### Share on other sites
bishop_pass    109
Use a hash-table, certainly, for a large data-set. That does not preclude anything else that I mentioned. I only mentioned assoc so that he could become familiar with different ways of structuring data.

You are doomed to mediocrity if you adhere to OOP all your programming career. Do yourself a favor and read some classical papers in AI.