From: ab talebi
Subject: Iteration & car/cdr-recursion
Date: 
Message-ID: <3bf506a3.5261597@news.online.no>
I try to combine Iteration technique and car/cdr recursion to search
in a database. Consider this peace of program for a datase wich look
like this:

name		george
familyname	bush
age		29
tlf		555-432343
=
name		cathrine
familyname	bush
age		18
tlf		555-55432
=
name		george
familyname	mc donnald
age		32
tlf		555-22222
tlf		555-33333
=

;; I put the database in a variable
(setf data-file (read-database "c:\database.txt"))

(defun read-entry (stream)
  (loop
      for line = (read-line stream nil nil)
      when (null line)
      return stream
      until  (string-equal line "=")
      collect 
	(multiple-value-bind (key position) (let ((*read-eval* nil))
					      (read-from-string line))
	  (loop 
	      while (eq #\tab (char line position))
	      do (incf position))	; skip multiple tabs
	  (list key
		(subseq line position)))))

;; this converts the database into lists
(defun read-database (pathname)
  (with-open-file (stream pathname :direction :input)
    (loop
	for address = (read-entry stream)
	until (eq address stream)
	collect address)))

(defun name (x)
  (and (consp x) (eq (car x) 'name)))

(defun tlf (x)
  (and (consp x) (eq (car x) 'tlf)))

(defun get-name ()
  (cdar (remove-if-not #'name data-file)))


(defun get-tlf ()
  (cdar (remove-if-not #'tlf data-file)))

(defun get-tlf-info (name)
  (cond ((null name) nil)
        ((equal (cdar (remove-if-not #'get-name (read-database
data-file))) 
                name)
         (cons (cdar (remove-if-not #'get-nr (read-database))) 
               (get-tlf-nr (cdr datafile))))))


I have already problem with:
(remove-if-not #'name '(name george))
which will return nil and I expect it to return GEORGE

and the main function (get-tlf-info 'george) that is supposed to give
me all the tlf.numbers to all the persons with the name george will
give me this error-message:

Error: Argument  is not of type PATHNAME, STRING, or FILE-STREAM. 

I also tried (get-tlf-info "c:\database.txt") it gives the same error
message.

ab talebi

From: Kent M Pitman
Subject: Re: Iteration & car/cdr-recursion
Date: 
Message-ID: <sfwy9l6c06k.fsf@shell01.TheWorld.com>
············@yahoo.com (ab talebi) writes:

> I have already problem with:
> (remove-if-not #'name '(name george))
> which will return nil and I expect it to return GEORGE

I'm not sure if I understand your desire here.

REMOVE-IF-NOT takes a predicate as its first argument, not an item.
#'NAME would be a function whose name is NAME.  If you want to remove
the symbol called NAME, you want (remove 'name '(name george)) which
will return (GEORGE) [not GEORGE].   No built-in removal function is
going to return the symbol GEORGE [i.e., as a symbol instead of a list
of symbols] since removal functions turn lists into other lists [of the
same or smaller length].

This whole thing where to find the value of an alist item, you remove 
everything in the alist that is not the item, though, is very misguided.
I recommend instead using FIND or ASSOC to *find* the item and then
destructure the result of that.

> and the main function (get-tlf-info 'george) that is supposed to give
> me all the tlf.numbers to all the persons with the name george will
> give me this error-message:
> 
> Error: Argument  is not of type PATHNAME, STRING, or FILE-STREAM. 
> 
> I also tried (get-tlf-info "c:\database.txt") it gives the same error
> message.

Make sure to double your backslashes (\).  Backslash is an escape character
in strings.  It syntactically quotes the next character following.

 "\\" is a one-letter string containing a backslash (\)

 "\"" is a one-letter string containing a doublequote (")

 "\:" (from your example) is a one-letter string containing a colon,
      and is more commonly written ":" since colon requires no quoting.

So "C:\database.txt" will be seen by Lisp the same as "C:database.txt",
which may not be what you want.
From: Barry Margolin
Subject: Re: Iteration & car/cdr-recursion
Date: 
Message-ID: <6ZaJ7.47$I25.5617@burlma1-snr2>
In article <···············@shell01.TheWorld.com>,
Kent M Pitman  <······@world.std.com> wrote:
>············@yahoo.com (ab talebi) writes:
>
>> I have already problem with:
>> (remove-if-not #'name '(name george))
>> which will return nil and I expect it to return GEORGE
>
>I'm not sure if I understand your desire here.
>
>REMOVE-IF-NOT takes a predicate as its first argument, not an item.
>#'NAME would be a function whose name is NAME.

I think you missed this in his post:

(defun name (x)
  (and (consp x) (eq (car x) 'name)))

So NAME is a predicate that tells whether something is a cons whose car is
NAME.  It would be more consistent with Lisp naming conventions if this
function were called NAMEP.

His problem is that REMOVE-IF-NOT doesn't pass the conses that form the
backbone of the list to the predicate, it passes the list elements.  So he
should change his predicate to:

(defun namep (x)
  (eq x 'name))

or switch to REMOVE, as you said.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Steve Long
Subject: Re: Iteration & car/cdr-recursion
Date: 
Message-ID: <3BF5EBDE.2943D256@isomedia.com>
It would have been simpler if he had just posted his homework problem.

sl

Barry Margolin wrote:

> In article <···············@shell01.TheWorld.com>,
> Kent M Pitman  <······@world.std.com> wrote:
> >············@yahoo.com (ab talebi) writes:
> >
> >> I have already problem with:
> >> (remove-if-not #'name '(name george))
> >> which will return nil and I expect it to return GEORGE
> >
> >I'm not sure if I understand your desire here.
> >
> >REMOVE-IF-NOT takes a predicate as its first argument, not an item.
> >#'NAME would be a function whose name is NAME.
>
> I think you missed this in his post:
>
> (defun name (x)
>   (and (consp x) (eq (car x) 'name)))
>
> So NAME is a predicate that tells whether something is a cons whose car is
> NAME.  It would be more consistent with Lisp naming conventions if this
> function were called NAMEP.
>
> His problem is that REMOVE-IF-NOT doesn't pass the conses that form the
> backbone of the list to the predicate, it passes the list elements.  So he
> should change his predicate to:
>
> (defun namep (x)
>   (eq x 'name))
>
> or switch to REMOVE, as you said.
>
> --
> Barry Margolin, ······@genuity.net
> Genuity, Woburn, MA
> *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
> Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.