Re: building other EQUIV?-like predicates William D Clinger 11 Mar 2006 02:55 UTC

Sebastian Egner raised an excellent point:

> In many cases I need an application-specific
> equivalence which is not among the predefined
> ones. For example, it should deal with cyclic
> structures the way EQUIV? does, but floats are
> compared only up to a certain tolerance (not
> that this results in an actual 'equivalence,'
> but it is often needed as a predicate anyhow).
> Another example is the presence of user-defined
> record types; equivalence predicates that are
> meaningful for the application can ignore some
> fields while recursing only on others.
>
> In these situations, I would still end up implementing a
> lot of code similar to the reference implementation you
> give but with little modifications in the recursion, or
> for the atomic types.

It would not be hard to provide parameterized
versions, say equivalent? and dag-equivalent?,
that take a predicate as their first argument
and use that predicate when comparing leaf nodes
(defined as anything that isn't a pair or vector).

Then (equiv? x y) would be like (equivalent? eqv? x y),
and (dag-equiv? x y) like (dag-equivalent? eqv? x y).
Your example might be something like

(define myequiv?
  (let* ((epsilon 1e-14)
         (leaf-equal? (lambda (x y)
                        (if (and (complex? x) (complex? y))
                            (< (magnitude (- x y))
                               (* epsilon
                                  (max 1.0
                                       (magnitude x)
                                       (magnitude y))))
                            (eqv? x y)))))
    (lambda (x y)
      (equivalent? leaf-equal? x y))))

It might be better to define make-equiv-predicate
and make-dag-equiv-predicate, which would take a
total predicate as their lone argument and return
a recursive binary predicate as their result.

Will