Up to this point, I've shown you various comparison functions without really saying much about the differences between them. In this chapter, I'll (finally) tell you about how and why the comparison functions differ and offer some guidelines for their proper use.
Lisp has a core set of comparison functions that work on virtually any kind of object. These are:
EQ
EQL
EQUAL
EQUALP
The tests with the shorter names support stricter definitions of equality. The tests with the longer implement less restrictive, perhaps more intuitive, definitions of equality. We'll learn about each of the four definitions in the following sections.
EQ
is true for identical symbols. In fact, it's true
for any identical object. In other words, an object is
EQ
to itself. Even a composite object, such as a list,
is EQ
to itself. (But two lists are not
EQ
just because they look the same when printed; they
must truly be the same list to be EQ
.) Under
the covers, EQ
just compares the memory addresses of
objects.
The reason that symbols are EQ when they have the same name (and are in the same package) is that the Lisp reader interns symbols as it reads them. The first time the reader sees a symbol, it creates it. On subsequent appearances, the reader simply uses the existing symbol.
EQ
is not guaranteed to be true for identical
characters or numbers. This is because most Lisp systems don't
assign a unique memory address to a particular number or character;
numbers and characters are generally created as needed and stored
temporarily in the hardware registers of the processor.
EQL
retains EQ
's notion of equality,
and extends it to identical numbers and characters. Numbers must
agree in value and type; thus 0.0 is not
EQL
to 0. Characters must be truly identical;
EQL
is case sensitive.
EQ
and EQL
are not generally true for
lists that print the same. Lists that are not EQ
but
have the same structure will be indistinguishable when printed; they
will also be EQUAL
.
Strings are also considered EQUAL
if they print the
same. Like EQL
, the comparison of characters within strings
is case-sensitive.
EQUALP
is the most permissive of the core comparison
functions. Everything that is EQUAL
is also EQUALP
.
But EQUALP
ignores case distinctions between characters, and
applies the (typeless) mathematical concept of equality to numbers; thus
0.0 is EQUALP
to 0.
Furthermore, EQUALP
is true if corresponding elements
are EQUALP
in the following composite data types:
The generality of the above longer-named tests comes with a price. They must test the types of their arguments to decide what kind of equality is applicable; this takes time.
EQ
is blind to type of an object; either the objects
are the same object, or they're not. This kind of test typically
compiles into one or two machine instructions and is very fast.
You can avoid unnecessary runtime overhead by using the most restrictive (shortest-named) test that meets your needs.
If you know the type of your data in advance, you can use comparisons that are specialized to test that particular type of data. Tests are available for characters, strings, lists, and numbers. And, of course, there are also comparisons for other relationships besides equality.
CHAR=
CHAR/=
CHAR<
CHAR<=
CHAR>
CHAR>=
CHAR-EQUAL
CHAR-NOT-EQUAL
STRING=
STRING/=
STRING<
STRING<=
STRING>
STRING>=
STRING-EQUAL
STRING-NOT-EQUAL
TREE-EQUAL