Chapter 17 - Not All Comparisons are Equal

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.

The longer the test, the more it tells you

Lisp has a core set of comparison functions that work on virtually any kind of object. These are:

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

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 is also true for identical numbers and characters

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.

EQUAL is usually true for things that print the same

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 ignores number type and character case

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:

Longer tests are slower; know what you're comparing

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.

Specialized tests run faster on more restricted data types

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.


Contents | Cover
Chapter 16 | Chapter 18
Copyright © 1995-1999, David B. Lamkins
All Rights Reserved Worldwide

This book may not be reproduced without the written consent of its author. Online distribution is restricted to the author's site.