recursionschemeracketequalityr5rs

# Recursive numeric equality in Scheme

It seems that Scheme considers integer and floating point versions of a number to be different when using equal?, but the same when using = to compare them:

``````(equal? 2 2.0)  ; => #f
(= 2 2.0)       ; => #t
``````

However, if I have a recursive structure with some numeric parts (or even a simple list of numbers), is there a method to compare them that uses = for numeric comparisons?

``````(equal? '(2 3) '(2.0 3.0))  ; => #f
(= '(2 3) '(2.0 3.0))       ; error: contract violation
``````

I can write my own equality checker, something like this:

``````(define myequal?
(lambda (x y)
(cond ((and (null? x) (null? y)) #t)
((or (null? x) (null? y)) #f)
((and (pair? x) (pair? y))
(and (myequal? (car x) (car y))
(myequal? (cdr x) (cdr y))))
((or (pair? x) (pair? y)) #f)
((and (number? x) (number? y)) (= x y))
((or (number? x) (number? y)) #f)
(else (equal? x y)))))
``````

But it seems like this would be a common enough task that Scheme might have a builtin method to do this.

Solution

• In Racket you can build the notion of equality that you want with the help of the `equal?/recur` built-in procedure:

``````;; equalish? : Any Any -> Boolean
;; Like equal?, but use = for numbers (including within compound data)
(define (equalish? a b)
(if (and (number? a) (number? b))
(= a b)
(equal?/recur a b equalish?)))

(equalish? '(2 3) '(2.0 3.0))
;; => #t
``````

The `equal?/recur` procedure handles recurring through pairs, structures, etc.