Newsgroups: comp.lang.lisp
Path: cantaloupe.srv.cs.cmu.edu!rochester!udel!gatech!howland.reston.ans.net!pipex!dircon!rheged!simon
From: simon@rheged.dircon.co.uk (Simon Brooke)
Subject: Re: Help with COND
Message-ID: <D8AvEr.78H@rheged.dircon.co.uk>
Organization: none. Disorganization: total.
References: <3olsng$brt@news.umbc.edu> <3olsto$btu@news.umbc.edu>
Date: Tue, 9 May 1995 07:28:02 GMT
Lines: 85

In article <3olsto$btu@news.umbc.edu>,
Michael Eilman <eilman@midget.towson.edu> wrote:
>Michael Eilman (eilman@midget.towson.edu) wrote:
>: I am kinda new to LISP and I am having a little trouble with a cond + 
>: others statement.  Basically what I am trying to do is write a condition 
>: statement which compares a word to the first word in a list of lists.  
>: The function looks much like this:
>
>: (defun look (pathlist room)
>: 	(cond (nil (pathlist) null)
>:               (eq (car(car(pathlist))) room) pprint (cdr(car(pathlist))))
>:               (t (look (cdr(pathlist)) room ))))
>
>: can anyone help me????
>
>The error that I get is that " the variable eq is not defined".

OK, your problem with COND is a very standard beginner problem, and is
caused by a misunderstanding of what COND does. This is because COND
is unlike anything in any other programming language. However, it's
very powerful, very flexible, and quite simple, and well worth
learning.

The function COND takes N arguments, where each argument is a list. 
It evaluates the CAR of each argument in turn, until one evaluates to
non-NIL. It then evaluates each of the remaining elements of that
argument in turn and returns the value of the last.

If none of the CARs of the arguments evaluate to non-nil, COND returns
NIL.

So *from the COND point of view* your function ought to read something
like: 

version one:

(defun look (pathlist room)
  (cond
   ((null pathlist) nil)
   ((eq (caar pathlist) room) (pprint (cdar pathlist)))
   (t (look (cdr pathlist) room))))

So far so good. However, if what you want to do is apply the same
operation to each element in a flat list, tail recursion is probably
not the best way to do it. Have a look at the documentation of the MAP
functions, especially MAPCAR. It's quite likely that what you actually
want is:

version two:

(defun look (pathlist room)
  (mapcar				;; or another MAP function. If
					;; you aren't interested in
					;; the return value it doesn't
					;; much matter which.

   '(lambda (path) 
      (cond ((eq (car path) room) (pprint (cdar path)))))
   pathlist))

Now I've understood what you are working with, I realise that
your pathlist is actually an association list -- that is, a flat list
of (token . value) pairs. LISP provides a standard function for
retreiving values out of such lists, called ASSOC. So a still better
solution would be:

version three:

(defun look (pathlist room)
  (pprint (assoc room pathlist)))	;; Now there's the
					;; expressiveness of LisP!

Note that versions one and three will pprint the value of the first
match and then exit, whereas version two will pprint the values of all
matches.

Final point: if your pathlist is very large, you might want to try
recoding it as a hash-array.

Hope this helps.

-- 
------- simon@rheged.dircon.co.uk (Simon Brooke)

			-- mens vacua in medio vacuo --
