Comparing Stuff: eq, equal, and More

There’s a lot of beautiful symmetry in Lisp. One part of Lisp that isn’t so beautiful, though, involves the commands for comparing things.

If you want to compare two values in Lisp to find out if they are “the same,” you will find a bewildering assortment of different functions that purport to accomplish this. Of these, equal, eql, eq, =, string-equal, and equalp are the most commonly used. A Lisper must understand the subtleties of these functions intimately in order to know how to compare values correctly.

image with no caption

Before we start dissecting this madness, let me give you Conrad’s Rule of Thumb for Comparing Stuff. Follow this rule, and though you may not be writing the world’s cleanest Lisp code, you will probably be able to post some samples to a newsgroup without more seasoned Lispers running you out of town with torches and pitchforks.

image with no caption

Symbols should always be compared to other symbols with eq:

> (defparameter *fruit* 'apple)

*FRUIT*

> (cond ((eq *fruit* 'apple) 'its-an-apple)
        ((eq *fruit* 'orange) 'its-an-orange))

ITS-AN-APPLE

The eq function is the simplest of all the Lisp comparison functions, and it’s also very fast. It doesn’t really work for comparing items besides symbols, but if you consider the central role symbols play in Lisp, you’ll realize how useful this function can be. Experienced Lispers might look down on code if it compares two things, known to be symbols, with something other than eq.

Note

eq can also be used to compare conses (the links created by the cons command). However, it returns true values only when a cons is compared directly to itself, created by the same cons call. This means, two unrelated conses that “look” exactly the same can fail an eq test. Since eq can check a cons cell only against itself, using eq with conses isn’t really that useful for a beginner. However, an advanced Lisper may want to compare conses with eq under certain circumstances.

If you’re not dealing with two symbols, just use equal. This command will tell you when two things are isomorphic, meaning they “look the same.” It works for the whole suite of basic Lisp datatypes, as shown here:

;;comparing symbols
> (equal 'apple 'apple)

T

;;comparing lists
> (equal (list 1 2 3) (list 1 2 3))

T

;;Identical lists created in different ways still compare as the same
> (equal '(1 2 3) (cons 1 (cons 2 (cons 3))))

T

;;comparing integers
> (equal 5 5)

T

;;comparing floating point numbers
> (equal 2.5 2.5)

T

;;comparing strings
> (equal "foo" "foo")

T

;;comparing characters
> (equal #a #a)

T

As you can see, most items in Lisp can be effectively compared with equal, including strings and characters (which are discussed in the next chapter).

Now that you know the bare minimum about Lisp comparisons to fake your way through your next cocktail party, let’s look at all the other comparison commands.

image with no caption

The eql command is similar to the eq command, but unlike eq, it also handles comparisons of numbers and characters:

;;comparing symbols
> (eql 'foo 'foo)

T

;;comparing numbers
> (eql 3.4 3.4)

T

;;comparing characters
> (eql #a #a)

T

The equalp command is essentially the same as the equal command, except that it can handle some difficult comparison cases with a bit of extra sophistication. For instance, it can compare strings with different capitalizations and can compare integers against floating-point numbers:

;;comparing strings with different CAPS
> (equalp "Bob Smith" "bob smith")
T
;;comparing integers against floating point numbers
> (equalp 0 0.0)
T

The remaining comparison commands are just specializations for specific datatypes. Otherwise, they are similar to equal. For instance, the = (equal sign) function handles numbers, string-equal handles strings, and char-equal handles characters.

I hope that you can now appreciate just how seriously Lispers take comparisons.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.179.85