Archived

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

master_ball

Lisp: traversing a cons list

Recommended Posts

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 this post


Link to post
Share on other sites

  
(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 this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
I am not saying I am trying to think in OO, I was checking to see if you think my idea of having a push and pop function and find and find all to deal with the data sets would be obvious to someone who is used to think with OO or simply good ideas -or actually bad ideas!

Share this post


Link to post
Share on other sites