DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH
 

(r5rs) Equivalence predicates

Info Catalog (r5rs) Standard procedures (r5rs) Standard procedures (r5rs) Numbers
 
 6.1 Equivalence predicates
 ==========================
 
 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.  `Eqv?' is slightly less discriminating than `eq?'.
 
  -- procedure: eqv? obj1 obj2
      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.  This relation is left slightly
      open to interpretation, but the following partial specification of
      `eqv?' holds for all implementations of Scheme.
 
      The `eqv?' procedure returns #t if:
 
         * OBJ1 and OBJ2 are both #t or both #f.
 
         * OBJ1 and OBJ2 are both symbols and
 
           (string=? (symbol->string obj1)
                     (symbol->string obj2))
                                             ==>  #t
 
                _Note:_ This assumes that neither OBJ1 nor OBJ2 is an
                "uninterned symbol" as alluded to in section 
                Symbols.  This report does not presume to specify the
                behavior of `eqv?' on implementation-dependent
                extensions.
 
         * OBJ1 and OBJ2 are both numbers, are numerically equal (see
           `=', section  Numbers), and are either both exact or
           both inexact.
 
         * OBJ1 and OBJ2 are both characters and are the same character
           according to the `char=?' procedure (section 
           Characters).
 
         * both OBJ1 and OBJ2 are the empty list.
 
         * OBJ1 and OBJ2 are pairs, vectors, or strings that denote the
           same locations in the store (section  Storage model).
 
         * OBJ1 and OBJ2 are procedures whose location tags are equal
           (section  Procedures).
 
 
      The `eqv?' procedure returns #f if:
 
         * OBJ1 and OBJ2 are of different types (section 
           Disjointness of types).
 
         * one of OBJ1 and OBJ2 is #t but the other is #f.
 
         * OBJ1 and OBJ2 are symbols but
 
           (string=? (symbol->string OBJ1)
                     (symbol->string OBJ2))
                                             ==>  #f
 
         * one of OBJ1 and OBJ2 is an exact number but the other is an
           inexact number.
 
         * OBJ1 and OBJ2 are numbers for which the `=' procedure returns
           #f.
 
         * OBJ1 and OBJ2 are characters for which the `char=?' procedure
           returns #f.
 
         * one of OBJ1 and OBJ2 is the empty list but the other is not.
 
         * OBJ1 and OBJ2 are pairs, vectors, or strings that denote
           distinct locations.
 
         * OBJ1 and OBJ2 are procedures that would behave differently
           (return different value(s) or have different side effects)
           for some 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
      (let ((p (lambda (x) x)))
        (eqv? p p))                          ==>  #t
 
      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.
 
      (eqv? "" "")                           ==>  _unspecified_
      (eqv? '#() '#())                       ==>  _unspecified_
      (eqv? (lambda (x) x)
            (lambda (x) x))                  ==>  _unspecified_
      (eqv? (lambda (x) x)
            (lambda (y) y))                  ==>  _unspecified_
 
      The next set of examples shows the use of `eqv?' with procedures
      that have local state.  `Gen-counter' must return a distinct
      procedure every time, since each procedure has its own internal
      counter.  `Gen-loser', however, returns equivalent procedures each
      time, since the local state does not affect the value or side
      effects of the procedures.
 
      (define gen-counter
        (lambda ()
          (let ((n 0))
            (lambda () (set! n (+ n 1)) n))))
      (let ((g (gen-counter)))
        (eqv? g g))                          ==>  #t
      (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))                          ==>  #t
      (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
 
      Since it is an error to modify constant objects (those returned by
      literal expressions), implementations are permitted, though not
      required, to share structure between constants where appropriate.
      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
 
           _Rationale:_ The above definition of `eqv?' allows
           implementations latitude in their treatment of procedures and
           literals:  implementations are free either to detect or to
           fail to detect that two procedures or two literals are
           equivalent to each other, and can decide whether or not to
           merge representations of equivalent objects by using the same
           pointer or bit pattern to represent both.
 
 
  -- procedure: eq? obj1 obj2
      `Eq?' is similar to `eqv?' except that in some cases it is capable
      of discerning distinctions finer than those detectable by `eqv?'.
 
      `Eq?' and `eqv?' are guaranteed to have the same behavior on
      symbols, booleans, the empty list, pairs, procedures, and non-empty
      strings and vectors.  `Eq?''s behavior on numbers and characters is
      implementation-dependent, but it will always return either true or
      false, and will return true only when `eqv?' would also return
      true.  `Eq?' may also behave differently from `eqv?' on empty
      vectors 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))                           ==>  #t
      (let ((p (lambda (x) x)))
        (eq? p p))                           ==>  #t
 
           _Rationale:_ It will usually be possible to implement `eq?'
           much more efficiently than `eqv?', for example, as a simple
           pointer comparison instead of as some more complicated
           operation.  One reason is that it may not be possible to
           compute `eqv?' of two numbers in constant time, whereas `eq?'
           implemented as pointer comparison will always finish in
           constant time.  `Eq?' may be used like `eqv?' in applications
           using procedures to implement objects with state since it
           obeys the same constraints as `eqv?'.
 
 
  -- library procedure: equal? obj1 obj2
      `Equal?' recursively compares the contents of pairs, vectors, and
      strings, applying `eqv?' on other objects such as numbers and
      symbols.  A rule of thumb is that objects are generally `equal?'
      if they print the same.  `Equal?' may fail to terminate if its
      arguments are circular data structures.
 
      (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? (lambda (x) x)
              (lambda (y) y))                ==>  _unspecified_
 
 
Info Catalog (r5rs) Standard procedures (r5rs) Standard procedures (r5rs) Numbers
automatically generated byinfo2html