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