From: Thomas Strathmann
Subject: What's wrong here?
Date: 
Message-ID: <396DCA6D.4C784F87@gmx.de>
This is a multi-part message in MIME format.
--------------5C8429E67E3846C6EC56669B
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi,

I'm a beginning LISP "programmer" and I have a problem with
a short program to check a user id and password. Maybe you
can help me. Thank you!

Thomas
--------------5C8429E67E3846C6EC56669B
Content-Type: text/plain; charset=us-ascii;
 name="login.l"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="login.l"

(setq users (cons (list "a" "b" "c") (list "x" "y" "z")))

(defun adduser (id pwd)
  (push id (car users))
  (push pwd (cdr users))
  "user added")

(defun who ()
  (setq i (- (list-length users) 1))
  (loop
   (print (nth i (car users)))
   (print (nth i (cdr users)))
   (setq i (- i 1))
   (when (< i 0) (return))))

(defun login (id pwd)
  (setq logged-in NIL)
  (setq i (- (list-length users) 1))
  (loop
   (cond
    ((eq id (nth i (car users)))
     (cond
      ((eq pwd (nth i (cdr users)))) (setq logged-in t)))
    (setq logged-in NIL))
   (setq i (- i 1))
   (when (= i 0) (return)))
   logged-in)

--------------5C8429E67E3846C6EC56669B--

From: Barry Margolin
Subject: Re: What's wrong here?
Date: 
Message-ID: <TEkb5.4$BL6.332@burlma1-snr2>
In article <·················@gmx.de>,
Thomas Strathmann  <·········@gmx.de> wrote:
>I'm a beginning LISP "programmer" and I have a problem with
>a short program to check a user id and password. Maybe you
>can help me. Thank you!

The problem is you're using EQ to compare strings.  EQ is used to tell you
whether two objects are the same object, not whether that just look the
same.  Two strings that happen to have the same contents are not the same
object, and EQ will return NIL.  Try (eq "foo" "foo") and you'll see.

Use STRING-EQUAL or STRING= (depending on whether you want case
sensitivity) to compare strings.

BTW, it would probably be a better design to use an association list rather
than separate lists of usernames and passwords.  Or if you're going to loop
through a list, use something like DOLIST rather than lots of calls to
NTH.  And variables like I in WHO and LOGIN should be local variables bound
with LET.

>
>Thomas
>-=-=-=-=-=-
>
>(setq users (cons (list "a" "b" "c") (list "x" "y" "z")))
>
>(defun adduser (id pwd)
>  (push id (car users))
>  (push pwd (cdr users))
>  "user added")
>
>(defun who ()
>  (setq i (- (list-length users) 1))
>  (loop
>   (print (nth i (car users)))
>   (print (nth i (cdr users)))
>   (setq i (- i 1))
>   (when (< i 0) (return))))
>
>(defun login (id pwd)
>  (setq logged-in NIL)
>  (setq i (- (list-length users) 1))
>  (loop
>   (cond
>    ((eq id (nth i (car users)))
>     (cond
>      ((eq pwd (nth i (cdr users)))) (setq logged-in t)))
>    (setq logged-in NIL))
>   (setq i (- i 1))
>   (when (= i 0) (return)))
>   logged-in)
>
>-=-=-=-=-=-


-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, 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: Kent M Pitman
Subject: Re: What's wrong here?
Date: 
Message-ID: <sfwwviok53m.fsf@world.std.com>
Barry Margolin <······@genuity.net> writes:

> Two strings that happen to have the same contents are not the same
> object, and EQ will return NIL.  Try (eq "foo" "foo") and you'll see.

Actually, Barry, this may not be such a good example.  I could imagine
(eq "foo" "foo") returning true in MCL.  That is, any Lisp that pre-compiles
its code, so that (eval x) == (funcall (compile nil `(lambda () ,x)))
is in the situation where a compiler might have decided to canonicalize
constants, and...

Though less dramatic/perspicuous, (eq (copy-seq "foo") (copy-seq "foo"))
probably is more reliable.

> Use STRING-EQUAL or STRING= (depending on whether you want case
> sensitivity) to compare strings.

Right.
 
> BTW, it would probably be a better design to use an association list rather
> than separate lists of usernames and passwords.  Or if you're going to loop
> through a list, use something like DOLIST rather than lots of calls to
> NTH.  And variables like I in WHO and LOGIN should be local variables bound
> with LET.

I agree with this advice as well.
From: vsync
Subject: Re: What's wrong here?
Date: 
Message-ID: <87wvin25db.fsf@piro.quadium.net>
Kent M Pitman <······@world.std.com> writes:

> Barry Margolin <······@genuity.net> writes:
> 
> > Two strings that happen to have the same contents are not the same
> > object, and EQ will return NIL.  Try (eq "foo" "foo") and you'll see.
> 
> Actually, Barry, this may not be such a good example.  I could imagine
> (eq "foo" "foo") returning true in MCL.  That is, any Lisp that pre-compiles
> its code, so that (eval x) == (funcall (compile nil `(lambda () ,x)))
> is in the situation where a compiler might have decided to canonicalize
> constants, and...
> 
> Though less dramatic/perspicuous, (eq (copy-seq "foo") (copy-seq "foo"))
> probably is more reliable.

Yes, but to a newbie, that might be more help than hurt.  ("What's
copy-seq?")  And short and sweet is cool.  Why not just say:
`(eq "foo" "foo") is not guaranteed to return T."?

-- 
vsync
http://quadium.net/ - last updated Fri Jun 30 22:55:16 MDT 2000
(cons (cons (car (cons 'c 'r)) (cdr (cons 'a 'o))) ; Orjner
      (cons (cons (car (cons 'n 'c)) (cdr (cons nil 's))) nil)))
From: Kalle Olavi Niemitalo
Subject: Re: What's wrong here?
Date: 
Message-ID: <izn1z0ydqz1.fsf@stekt34.oulu.fi>
I haven't programmed much in Common Lisp yet (more in Emacs Lisp) but
maybe I can help.

Thomas Strathmann <·········@gmx.de> writes:

> (setq users (cons (list "a" "b" "c") (list "x" "y" "z")))

I think an association list would be more lispy:

  (defvar *users* (("a" . "x") ("b" . "y") ("c" . "z")))

This would of course require many changes in the program.

> (defun who ()
>   (setq i (- (list-length users) 1))
[...]

Please learn about LET.

>     ((eq id (nth i (car users)))

This may be your problem: two strings aren't necessarily EQ even if
they contain the same characters.
From: Christopher J. Vogt
Subject: Re: What's wrong here?
Date: 
Message-ID: <396DE693.48AB1926@computer.org>
Thomas Strathmann wrote:
> 
> Hi,
> 
> I'm a beginning LISP "programmer" and I have a problem with
> a short program to check a user id and password. Maybe you
> can help me. Thank you!

Alternate versions to consider:


(defvar *users* '(("a" . "x") ("b" . "y") ("c" . "z")))

(defun adduser (id pwd)
  (push (cons id pwd) *users*)
  "user added")

(defun who ()
  (loop for user in *users* do
     (print (car user))
     (print (cdr user))))

(defun login (id pwd)
  (member (cons id pwd) *users* :test #'equal))


> 
> Thomas
> 
>   ----------------------------------------------------------------------------------------------------------------------------------------------------------------
> (setq users (cons (list "a" "b" "c") (list "x" "y" "z")))
> 
> (defun adduser (id pwd)
>   (push id (car users))
>   (push pwd (cdr users))
>   "user added")
> 
> (defun who ()
>   (setq i (- (list-length users) 1))
>   (loop
>    (print (nth i (car users)))
>    (print (nth i (cdr users)))
>    (setq i (- i 1))
>    (when (< i 0) (return))))
> 
> (defun login (id pwd)
>   (setq logged-in NIL)
>   (setq i (- (list-length users) 1))
>   (loop
>    (cond
>     ((eq id (nth i (car users)))
>      (cond
>       ((eq pwd (nth i (cdr users)))) (setq logged-in t)))
>     (setq logged-in NIL))
>    (setq i (- i 1))
>    (when (= i 0) (return)))
>    logged-in)