From: Mark Carter
Subject: EQ perplexity
Date: 
Message-ID: <434d5c40$0$49018$14726298@news.sunsite.dk>
In my code I have
	  (print auth)
	  (print (eq auth 'plain))
and that produces the results
PLAIN
NIL

Surely that isn't logically possible?

auth is defined in the function declaration:
(defun send-smtp (host from to subject message
		  &key (port 25)
		  (auth nil) (username "") (password  "")
		  cc bcc reply-to extra-headers
		  display-name(external-format :default))
    	...
	(print auth)
	(print (eq auth 'plain))
  	...
)

From: Mark Carter
Subject: Re: EQ perplexity
Date: 
Message-ID: <434d645b$0$49008$14726298@news.sunsite.dk>
Mark Carter wrote:
> In my code I have
>       (print auth)
>       (print (eq auth 'plain))
> and that produces the results
> PLAIN
> NIL
> 
> Surely that isn't logically possible?

Aha. When I type
    (print 'plain)
I get the result
    CL-SMTP::PLAIN
which explains why it thinks they aren't equal; and was rather 
unexpected by me.
From: Kaz Kylheku
Subject: Re: EQ perplexity
Date: 
Message-ID: <1129180451.155810.45080@z14g2000cwz.googlegroups.com>
Mark Carter wrote:
> Mark Carter wrote:
> > In my code I have
> >       (print auth)
> >       (print (eq auth 'plain))
> > and that produces the results
> > PLAIN
> > NIL
> >
> > Surely that isn't logically possible?
>
> Aha. When I type
>     (print 'plain)
> I get the result
>     CL-SMTP::PLAIN
> which explains why it thinks they aren't equal; and was rather
> unexpected by me.

Right. You probably defined the SMTP sending function in the CL-SMTP
package. And so, the symbols that make up the source code of that
function are interned in the CL-SMTP package. IN the function, a
comparison like (eq auth 'plain) really means (CL:EQ CL-SMTP::AUTH
'CL-SMTP::PLAIN).

But when you call the function from another package, as (smtp-send ...
:auth 'plain) you are really calling (CL-SMTP:SMTP-SEND ... :AUTH
'WHATEVER::PLAIN) where WHATEVER is whatever package the call is
written in.

Moral of the story: when you need symbols to represent the members of
abstract sets (the so called enumerated types), use keywords!

(smtp-send :auth :plain)

...

(if (eq auth :plain) ...)

etc. This way you avoid package mixups.

Note that certain standard features of Common Lisp, notably the LOOP
macro, deal with this in another way. No matter what package you are
in, you can write LOOP code, using symbols in that package:

 (in-package "FOO")

 (loop for x in list ...)

Here, the FOR symbol may well be encountered for the first time, and
interned as FOO::FOR.  The LOOP macro does not care. Why? Because it
compares the symbol names as strings, not EQ objects. Any symbol whose
name is "FOR" or "IN" will do as the designator of that respective
clause.

So that would be a possible design for the SMTP-SEND function, also.
From: Christian Lynbech
Subject: Re: EQ perplexity
Date: 
Message-ID: <87d5majzf7.fsf@chateau.defun.dk>
>>>>> "Mark" == Mark Carter <··@privacy.net> writes:

Mark> Surely that isn't logically possible?

Unfortunately, it is all too possible. Just because a symbol prints as
"PLAIN" does not mean that it is in fact the same symbol as 'plain.

It can depend on a number of things but often the problem is that the
value of `auth' and symbol compiled into the functions has been
interned in two different packages.

Try changing

    (print auth)

into something like

     (print (list auth 'plain (eq auth 'plain)))

Other tricks could be to stick in a call to `break' (will land you in
the debugger) and/or invoke `describe' to get the full details of the
symbols involved.

If you have any say in the matter, try to use keywords (ie. :plain
rather than 'plain) as these are much more robust against package
trickery.


------------------------+-----------------------------------------------------
Christian Lynbech       | christian ··@ defun #\. dk
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
                                        - ·······@hal.com (Michael A. Petonic)
From: Tim Daly Jr.
Subject: Re: EQ perplexity
Date: 
Message-ID: <874q7lzsee.fsf@beer.intern>
Christian Lynbech <·········@defun.dk> writes:

> >>>>> "Mark" == Mark Carter <··@privacy.net> writes:
> 
> Mark> Surely that isn't logically possible?
> 
> Unfortunately, it is all too possible. Just because a symbol prints as
> "PLAIN" does not mean that it is in fact the same symbol as 'plain.
...
> If you have any say in the matter, try to use keywords (ie. :plain
> rather than 'plain) as these are much more robust against package
> trickery.

It's also very robust to use STRING-EQUAL. It's case insensitive, and
it treats the symbols as string designators, disregarding their
package.

    CL-USER> (setf (readtable-case *readtable*) :invert)
    :invert
    CL-USER> (string-equal :foo 'sb-c::FOO)
    t


-- 
-Tim
From: Lars Rune Nøstdal
Subject: Re: EQ perplexity
Date: 
Message-ID: <pan.2005.10.12.22.31.35.131184@gmail.com>
Maybe,

(let ((auth 'PLAIN))
  (values auth
          (eq auth 'plain)
          (eq auth 'PLAIN)))

PLAIN
nil
t
...?

-- 
mvh,
Lars Rune Nøstdal
http://lars.nostdal.org/
From: Marco Antoniotti
Subject: Re: EQ perplexity
Date: 
Message-ID: <Qlg3f.29$pa3.14431@typhoon.nyu.edu>
Not is plain ANSI CL.

Lars Rune Nøstdal wrote:
> Maybe,
> 
> (let ((auth 'PLAIN))
>   (values auth
>           (eq auth 'plain)
>           (eq auth 'PLAIN)))
> 
> PLAIN
> nil
> t
> ...?
> 

In plain ANSI CL the values are

PLAIN
T
T

Cheers
--
Marco
From: Pascal Bourguignon
Subject: Re: EQ perplexity
Date: 
Message-ID: <87irw2wakp.fsf@thalassa.informatimago.com>
Marco Antoniotti <·······@cs.nyu.edu> writes:

> Not is plain ANSI CL.
>
> Lars Rune N�stdal wrote:
>> Maybe,
>> (let ((auth 'PLAIN))
>>   (values auth
>>           (eq auth 'plain)
>>           (eq auth 'PLAIN)))
>> PLAIN
>> nil
>> t
>> ...?
>> 
>
> In plain ANSI CL the values are
>
> PLAIN
> T
> T

For some definition of plain.


[80]> (setf (readtable-case *readtable*) :invert)
:invert
[81]> (let ((auth 'PLAIN)) (values auth (eq auth 'plain) (eq auth 'PLAIN)))
PLAIN ;
nil ;
t
[82]> (setf (readtable-case *readtable*) :upcase)
:UPCASE
[83]> (let ((auth 'PLAIN)) (values auth (eq auth 'plain) (eq auth 'PLAIN)))
PLAIN ;
T ;
T
[84]> 

-- 
"You cannot really appreciate Dilbert unless you read it in the
original Klingon"