================================================================== Hunk G starts here:
==================================================================
Since a pointer can point to any kind of thing, it's often good to know what kind of thing it does point to. For example, you might have a mixed list of dierent kinds of things, and want to go through the list, doing a dierent operation for each kind of object you encounter. For this, Scheme provides type predicates, which are procedures which test to see whether the pointed-to object is of a particular type.
You also often want to know whether two values refer to the same object, or to data structures with the same structure. For this, Scheme provides equality predicates.
These procedures are called \predicates" because they test whether a property is true of a value, and return a yes-or-no answer|that is, the boolean#tor the boolean#f. (This is like a \predicate"
The names of predicates generally end with a question mark, to signify that they return a boolean. When you write your own programs, it's good style to end the names of boolean-valued (true/false) functions with a question mark.
(An exception to this rule is the standard numeric comparison predicates like <,>, and =. By
the rule, they should have question marks after their names, but they're used very frequently and people generally recognize that they're predicates. We don't bother with question marks in their names, because it would clutter up arithmetic expressions.)
2.4.1 Type Predicates
Scheme provides built-in procedures to test whether values refer to objects of particular types. If you want to know whether the value of variablexis (a pointer to) pair, you can use the predicate pair?, like this: (pair? x).
Likewise, if you want to know if something is a number, you can use the predicate number?. If
you want to know whether a value is an integer, and not just some kind of number, you can use
integer?.
Several other type predicates are provided, for other data types we'll discuss later, including
string?,character?,vector?, and port?.
2.4.2 Equality Predicates
Equality predicates tell whether one value is \the same as" another. There are actually several important senses of \the same as," so Scheme provides four equality predicates.
Sometimes you want to know whether two data structures are structurally the same, with the same values in the same places. For example, you may want to know whether a list has the same structure and elements as another list. For this, you can use equal?, which does a deep,
element-by-element structural comparison.
For example (equal? '(1 2 3) '(1 2 3))returns#t, because the arguments are both lists con-
taining1,2, 3, in that order. equal?does a deep traversal of the data structure, so you can hand
it nested lists and other fairly complicated data structures as well. (Don't hand it structures with directed cycles of pointers, though, because it may loop forever without nding the end.)
equal? works to compare simple things, too. For example, (equal? 22 22) returns #t, and (equal? #t 15) returns #f. (Note that equal? can be used to compare things that may or may
not be of the same type, but if they're not, the answer will always be #f. Objects of dierent types
are neverequal?.)
Often you don't want to structurally compare two whole data structures|you just want to know if they're the exact same object. For example, given two pointers to lists, you may want to know if they're pointers to the very same list, not just two lists with the same elements.
For this, you use eq?. eq? compares two values to see if they refer to the same object. Since
all values in Scheme are (conceptually) pointers, this is just a pointer comparison, soeq?is always
fast.
(You might think that tagged immediate representations would requireeq?to be slower than a
simple pointer comparision, because it would have to check whether things were really pointers. This isn't actually true|eq? just compares the bit patterns without worrying whether they represent
pointers or immediates.)
Equality tests for numbers are treated specially. When comparing two values that are supposed to be numbers, = is the appropriate predicate. Using = has the advantage that using it on non-
numbers is an error, and Scheme will complain when it happens. If you make a mistake and have a non-number where you intend to have a number, this will often show you the problem. (You could also useequal?, but it won't signal an error when applied to non-numbers, and may be a little bit
slower.)
There is another equality predicate,eqv?, which does numeric comparisons on numbers (like=),
and identity comparisons (like eq?) on anything else.
================================================================== This is the end of Hunk G
TIME TO TRY IT OUT
At this point, you should go read Hunk H of the next chapter and work through the examples using a running Scheme system. Then return here and resume this chapter.
==================================================================
2.4.3 Choosing Equality Predicates (Hunk I)
================================================================== Hunk I starts here:
==================================================================
The reason that the =and eqv?predicates are needed is that the numeric system of Scheme is
not quite as clean as it could be, for eciency reasons.
Ideally, there would be exactly one copy of any numeric value, and all occurrences of that value would really be pointers to the same unique object. Then you could use eq?to compare numbers
for identity, just as you can for other kinds of values. (For example, there would be just one oating- point number with the value 2.36529, and any computation that returned that oating-point value would return a pointer to that unique object. ((eq? 2.36529 2.36529)would return #t.)
Unfortunately, for numbers it would be too expensive to do this|it would require keeping a table of all of the numbers in the system, and probing that table to eliminate duplicate copies of the same values. As a concession to eciency, Scheme allows multiple copies of the same number, and the=and eqv?predicates mask this wart in the language|they perform numeric comparisons
when faced with numbers, so that you don't have to worry about whether two numbers with the same value are literally the same object.
eqv? thus tests whether two values are \equivalent," when two objects with the same numeric
value are treated as \the same," like =, but all other objects are distinguished by their object
identity, like eq?. In general,
eq? is useful for fast identity (same object) comparisons of non-numbers, =performs numeric comparisons on numbers,
eqv? is like eq?, but treats copies of the same number as though they were the same object,
and
equal? performs a \deep" comparison of the structure of data structures. (It uses eqv? for
components that are numbers.)