In Paul Graham's book ANSI Common Lisp, while discussing symbol vs string manipulation, he says
Symbols can be compared in one step with
eql
..."
(p138). Here are two cases of symbol comparison:
(setq x 3)
3
(setq a 'x)
X
(setq b 'x)
X
(eq a b)
T
So, since a
and b
point to the same symbol object, named "X"
, they are eq
. However, this contrasts with
(setq a (copy-symbol 'x))
#:X
(setq b (copy-symbol 'x))
#:X
(symbol-name a)
"X"
(symbol-name b)
"X"
(eq a b)
NIL
(eql a b)
NIL
(equal a b)
NIL
(equalp a b)
NIL
Now, a
and b
point to different symbol
objects, even though they have the same symbol-name
and same print name. My questions are:
eql
rather than eq
, anda
and b
not at least equalp
?eql
over eq
?eql
is "more predictable" in the sense that it is less implementation-dependent.
E.g., non-immediate numbers (i.e.,
non-fixnum
s) can be non-eq
in some implementations and eq
in others:
(= 1.5d0 1.5d0)
=> T
(eql 1.5d0 1.5d0)
=> T
(eq 1.5d0 1.5d0)
=> T in some implementations, NIL in others
equalp
?That's what the spec says :-)
Note that it does violated the rule of thumb:
A rough rule of thumb is that two objects are
equal
if and only if their printed representations are the same.
The main non-histerical reason for this is that symbol, while being
"atomic", still carries many baggage (e.g., variable and function
bindings). IOW, a symbol
is
much more than its name.
Also, one generally expects that equal
forms evaluate to
equal
values, which cannot be the case if different symbols (with
possibly different bindings!) are evaluated as equal
.
Now, the only differences between equal
and equalp
are
=
structure
,
array
, and
hash-table
.None of these changes affects the "similar evaluation rule" above,
so there is no reason for equalp
to compare symbols based on
their names.
If you want to compare symbols by names, you can
use string=
:
(eq '#:a '#:a)
==> NIL
(equalp '#:a '#:a)
==> NIL
(string= '#:a '#:a)
==> T