Next: baselib math, Previous: baselib expressions, Up: baselib [Index]
A predicate is a procedure that always returns a boolean value
(#t
or #f
). An equivalence predicate is the
computational analogue of a mathematical equivalence relation (it is
symmetric, reflexive, and transitive). Of the equivalence predicates
described in this section, eq?
is the finest or most
discriminating, and equal?
is the coarsest. The eqv?
predicate is slightly less discriminating than eq?
.
The eqv?
procedure defines a useful equivalence relation on
objects. Briefly, it returns #t
if obj1 and obj2
should normally be regarded as the same object and #f
otherwise.
This relation is left slightly open to interpretation, but the following
partial specification of eqv?
must hold for all implementations.
The eqv?
procedure returns #t
if one of the following holds:
boolean=?
procedure.
symbol=?
procedure.
=
).
=
), and yield the same results (in the
sense of eqv?
) when passed as arguments to any other procedure
that can be defined as a finite composition of Scheme’s standard
arithmetic procedures.
char=?
procedure.
eqv?
in library section “Procedural layer”.
The eqv?
procedure returns #f
if one of the following
holds:
boolean=?
procedure returns #f
.
symbol=?
procedure returns #f
.
=
procedure returns #f
.
eqv?
) when passed as arguments to any other procedure that can be
defined as a finite composition of Scheme’s standard arithmetic
procedures.
char=?
procedure returns #f
.
car
,
cdr
, vector-ref
, string-ref
, or record accessors)
to both yields results for which eqv?
returns #f
.
NOTE The
eqv?
procedure returning#t
when obj1 and obj2 are number objects does not imply that=
would also return#t
when called with obj1 and obj2 as arguments.
(eqv? 'a 'a) ⇒ #t (eqv? 'a 'b) ⇒ #f (eqv? 2 2) ⇒ #t (eqv? '() '()) ⇒ #t (eqv? 100000000 100000000) ⇒ #t (eqv? (cons 1 2) (cons 1 2)) ⇒ #f (eqv? (lambda () 1) (lambda () 2)) ⇒ #f (eqv? #f 'nil) ⇒ #f
The following examples illustrate cases in which the above rules do not
fully specify the behavior of eqv?
. All that can be said about
such cases is that the value returned by eqv?
must be a boolean.
(let ((p (lambda (x) x))) (eqv? p p)) ⇒ unspecified (eqv? "" "") ⇒ unspecified (eqv? '#() '#()) ⇒ unspecified (eqv? (lambda (x) x) (lambda (x) x)) ⇒ unspecified (eqv? (lambda (x) x) (lambda (y) y)) ⇒ unspecified (eqv? +nan.0 +nan.0) ⇒ unspecified
The next set of examples shows the use of eqv?
with procedures
that have local state. Calls to gen-counter
must return a
distinct procedure every time, since each procedure has its own internal
counter. Calls to gen-loser
return procedures that behave
equivalently when called. However, eqv?
may not detect this
equivalence.
(define gen-counter (lambda () (let ((n 0)) (lambda () (set! n (+ n 1)) n)))) (let ((g (gen-counter))) (eqv? g g)) ⇒ unspecified (eqv? (gen-counter) (gen-counter)) ⇒ #f (define gen-loser (lambda () (let ((n 0)) (lambda () (set! n (+ n 1)) 27)))) (let ((g (gen-loser))) (eqv? g g)) ⇒ unspecified (eqv? (gen-loser) (gen-loser)) ⇒ unspecified (letrec ((f (lambda () (if (eqv? f g) 'both 'f))) (g (lambda () (if (eqv? f g) 'both 'g)))) (eqv? f g)) ⇒ unspecified (letrec ((f (lambda () (if (eqv? f g) 'f 'both))) (g (lambda () (if (eqv? f g) 'g 'both)))) (eqv? f g)) ⇒ #f
Implementations may share structure between constants where appropriate.
Furthermore, a constant may be copied at any time by the implementation
so as to exist simultaneously in different sets of locations. Thus the
value of eqv?
on constants is sometimes
implementation–dependent.
(eqv? '(a) '(a)) ⇒ unspecified (eqv? "a" "a") ⇒ unspecified (eqv? '(b) (cdr '(a b))) ⇒ unspecified (let ((x '(a))) (eqv? x x)) ⇒ #t
The eq?
predicate is similar to eqv?
except that in some
cases it is capable of discerning distinctions finer than those
detectable by eqv?
.
The eq?
and eqv?
predicates are guaranteed to have the
same behavior on symbols, booleans, the empty list, pairs, procedures,
non–empty strings, bytevectors, vectors, and records. The behavior of
eq?
on number objects and characters is
implementation–dependent, but it always returns either #t
or
#f
, and returns #t
only when eqv?
would also return
#t
. The eq?
predicate may also behave differently from
eqv?
on empty vectors, empty bytevectors, and empty strings.
(eq? 'a 'a) ⇒ #t (eq? '(a) '(a)) ⇒ unspecified (eq? (list 'a) (list 'a)) ⇒ #f (eq? "a" "a") ⇒ unspecified (eq? "" "") ⇒ unspecified (eq? '() '()) ⇒ #t (eq? 2 2) ⇒ unspecified (eq? #\A #\A) ⇒ unspecified (eq? car car) ⇒ #t (let ((n (+ 2 3))) (eq? n n)) ⇒ unspecified (let ((x '(a))) (eq? x x)) ⇒ #t (let ((x '#())) (eq? x x)) ⇒ unspecified (let ((p (lambda (x) x))) (eq? p p)) ⇒ unspecified
The equal?
predicate returns #t
if and only if the
(possibly infinite) unfoldings of its arguments into regular trees are
equal as ordered trees.
The equal?
predicate treats pairs and vectors as nodes with
outgoing edges, uses string=?
to compare strings, uses
bytevector=?
to compare bytevectors (stdlib bytevector),
and uses eqv?
to compare other nodes.
(equal? 'a 'a) ⇒ #t (equal? '(a) '(a)) ⇒ #t (equal? '(a (b) c) '(a (b) c)) ⇒ #t (equal? "abc" "abc") ⇒ #t (equal? 2 2) ⇒ #t (equal? (make-vector 5 'a) (make-vector 5 'a)) ⇒ #t (equal? '#vu8(1 2 3 4 5) (u8-list->bytevector '(1 2 3 4 5)) ⇒ #t (equal? (lambda (x) x) (lambda (y) y)) ⇒ unspecified (let* ((x (list 'a)) (y (list 'a)) (z (list x y))) (list (equal? z (list y x)) (equal? z (list x x)))) ⇒ (#t #t)
NOTE As Vicare extensions: structs are compared with
struct=?
and R6RS records are compared withrecord=?
.
NOTE The
equal?
procedure must always terminate, even if its arguments contain cycles.
Return #t
if obj is a procedure, otherwise return #f
.
(procedure? car) ⇒ #t (procedure? 'car) ⇒ #f (procedure? (lambda (x) (* x x))) ⇒ #t (procedure? '(lambda (x) (* x x))) ⇒ #f
Next: baselib math, Previous: baselib expressions, Up: baselib [Index]