Comparison Procedures¶
Overview¶
Comparison procedures test relationships between objects and return a boolean value. This implementation provides three distinct categories of comparison: numeric ordering, object equality, and type-specific equality, each suited to different circumstances.
Numeric Ordering
The numeric ordering procedures — =, <, >, <=, and >= —
compare numbers by value and accept any number of arguments, testing the
relationship between each consecutive pair. They operate across the full
numeric tower, automatically promoting arguments to a common type before
comparing. = additionally accepts complex arguments, since complex numbers
support equality testing even though they have no natural ordering; the
remaining four require real arguments. These procedures are discussed in full
in the Numerics section.
Object Equality
The three general equality predicates form a hierarchy of generality and computational cost, and choosing the right one for a given situation is important both for correctness and efficiency.
eq? is the most primitive and most efficient. It tests object identity
— two objects are eq? only if they are the exact same object in memory.
This gives reliable results for symbols (which are interned and therefore
unique), booleans, the empty list, and any object compared with itself. It
should not be used for numbers, characters, or compound objects, where
distinct objects with identical values are not guaranteed to be
pointer-identical.
eqv? extends eq? to cover value equality for atomic types: two
numbers are eqv? if they have the same type, exactness, and value; two
characters are eqv? if they have the same Unicode scalar value. For all
other types, eqv? falls back to pointer identity. Note that eqv?
is stricter than = for numbers: (eqv? 1 1.0) returns #f because
the two arguments differ in type and exactness, even though (= 1 1.0)
returns #t.
equal? is the most general predicate and performs deep structural
comparison. Two lists are equal? if they have the same length and all
corresponding elements are equal? recursively; likewise for vectors and
bytevectors. Two strings are equal? if they contain the same sequence of
characters. For numbers, equal? applies the same type-and-exactness
requirement as eqv?. For all other atomic types it behaves identically
to eqv?. Because equal? recurses into compound structures, it is
necessarily more expensive than eq? or eqv? for large objects. It
correctly handles circular and shared structure and will not loop infinitely
on cyclic lists.
As a rule of thumb: use eq? when comparing symbols or testing object
identity; use eqv? when comparing numbers or characters where type
matters; use equal? when comparing compound data structures by content.
Comparison Procedures¶
Numeric Comparison Procedures¶
equal (=)¶
- (= z1 z2 ...)
Returns
#tif all arguments are numerically equal,#fotherwise. Unlikeeqv?andequal?, this procedure compares by numeric value across types, so(= 1 1.0 1/1)returns#t. Accepts complex number arguments in addition to real numbers.- Parameters:
z1 (number) – Two or more numbers to compare.
- Returns:
#tif all arguments are numerically equal,#fotherwise.- Return type:
boolean
Example:
--> (= 1 1) #t --> (= 1 1.0) #t --> (= 1 1/1) #t --> (= 1 2) #f --> (= 1+0i 1) #t --> (= 1 1 1 1) #t
greater than (>)¶
- (> x1 x2 ...)
Returns
#tif the arguments are monotonically decreasing,#fotherwise. Arguments must be real numbers; complex numbers are not permitted.- Parameters:
x1 (real) – Two or more real numbers to compare.
- Returns:
#tif the arguments are monotonically decreasing,#fotherwise.- Return type:
boolean
Example:
--> (> 3 2) #t --> (> 2 3) #f --> (> 3 2 1) #t --> (> 3 3) #f --> (> 1/2 1/3) #t
less than (<)¶
- (< x1 x2 ...)
Returns
#tif the arguments are monotonically increasing,#fotherwise. Arguments must be real numbers; complex numbers are not permitted.- Parameters:
x1 (real) – Two or more real numbers to compare.
- Returns:
#tif the arguments are monotonically increasing,#fotherwise.- Return type:
boolean
Example:
--> (< 1 2) #t --> (< 2 1) #f --> (< 1 2 3) #t --> (< 1 1) #f --> (< 1/3 1/2) #t
greater than or equal (>=)¶
- (>= x1 x2 ...)
Returns
#tif the arguments are monotonically non-increasing,#fotherwise. Arguments must be real numbers; complex numbers are not permitted.- Parameters:
x1 (real) – Two or more real numbers to compare.
- Returns:
#tif the arguments are monotonically non-increasing,#fotherwise.- Return type:
boolean
Example:
--> (>= 3 2) #t --> (>= 3 3) #t --> (>= 2 3) #f --> (>= 3 2 2 1) #t
less than or equal (<=)¶
- (<= x1 x2 ...)
Returns
#tif the arguments are monotonically non-decreasing,#fotherwise. Arguments must be real numbers; complex numbers are not permitted.- Parameters:
x1 (real) – Two or more real numbers to compare.
- Returns:
#tif the arguments are monotonically non-decreasing,#fotherwise.- Return type:
boolean
Example:
--> (<= 1 2) #t --> (<= 1 1) #t --> (<= 2 1) #f --> (<= 1 1 2 3) #t
General Comparison Procedures¶
eq?¶
- (eq? obj1 obj2)
Returns
#tif obj1 and obj2 are the exact same object,#fotherwise. Comparison is by pointer identity — two objects areeq?only if they occupy the same location in memory.eq?is the most efficient equality predicate but the least general. It gives reliable results for symbols, booleans, the empty list, and other unique objects. It should not be used to compare numbers, characters, strings, pairs, or vectors, since two distinct objects with the same value are not guaranteed to be pointer-identical.- Parameters:
obj1 (any) – The first object to compare.
obj2 (any) – The second object to compare.
- Returns:
#tif obj1 and obj2 are the same object,#fotherwise.- Return type:
boolean
Example:
--> (eq? 'foo 'foo) #t --> (eq? '() '()) #t --> (eq? #t #t) #t --> (let ((x '(1 2))) (eq? x x)) #t --> (eq? '(1 2) '(1 2)) #f --> (eq? "hello" "hello") #f
eqv?¶
- (eqv? obj1 obj2)
Returns
#tif obj1 and obj2 are equivalent,#fotherwise.eqv?extendseq?by additionally considering numbers of the same type and value, and characters with the same Unicode scalar value, as equivalent — even if they are distinct objects in memory.For types not covered by these rules (pairs, vectors, strings, and other compound objects),
eqv?falls back to pointer identity. Useequal?for deep structural comparison of compound objects.Note that
eqv?requires both objects to be of the same type before comparing values, so(eqv? 1 1.0)returns#feven though(= 1 1.0)returns#t.- Parameters:
obj1 (any) – The first object to compare.
obj2 (any) – The second object to compare.
- Returns:
#tif obj1 and obj2 are equivalent,#fotherwise.- Return type:
boolean
Example:
--> (eqv? 42 42) #t --> (eqv? 1 1.0) #f --> (eqv? #\a #\a) #t --> (eqv? 'foo 'foo) #t --> (eqv? '() '()) #t --> (eqv? '(1 2) '(1 2)) #f
equal?¶
- (equal? obj1 obj2)
Returns
#tif obj1 and obj2 have the same structure and contents,#fotherwise.equal?performs a deep recursive comparison: two lists areequal?if they have the same length and each corresponding pair of elements isequal?; two vectors areequal?if they have the same length and each corresponding pair of elements isequal?; two strings areequal?if they contain the same sequence of characters; two bytevectors areequal?if they are of the same type and contain the same sequence of elements.For numbers,
equal?requires both the same type and the same exactness, so(equal? 2 2/1)returns#feven though(= 2 2/1)returns#t. For all other atomic types,equal?behaves likeeqv?.equal?correctly handles circular and shared list structures using cycle detection, and will not loop infinitely on circular lists.- Parameters:
obj1 (any) – The first object to compare.
obj2 (any) – The second object to compare.
- Returns:
#tif obj1 and obj2 are structurally equal,#fotherwise.- Return type:
boolean
Example:
--> (equal? '(1 2 3) '(1 2 3)) #t --> (equal? '(1 2 3) '(1 2 4)) #f --> (equal? #(1 2 3) #(1 2 3)) #t --> (equal? "hello" "hello") #t --> (equal? 2 2/1) #f --> (equal? '(1 (2 3)) '(1 (2 3))) #t