Equal?/recur examples

Hello,

reading the racket guide I found the equal?/recur function. I find difficult to understand how it works. Does somebody have some interesting examples?

Thank you

Matteo

Here's an example of one way I've used equal?/recur to compare syntax objects in test cases:

(require rackunit)

;; Works on fully wrapped, non-wrapped, and partially
;; wrapped values, and it checks that the inputs are
;; wrapped in all the same places. It checks scopes,
;; but it does not check source location.
(define-binary-check (check-stx=? stx=? actual expected))

;; Stx Stx -> Bool
(define (stx=? a b)
  (cond
    [(and (identifier? a) (identifier? b))
     (bound-identifier=? a b)]
    [(and (syntax? a) (syntax? b))
     (and (bound-identifier=? (datum->syntax a '||) (datum->syntax b '||))
          (stx=? (syntax-e a) (syntax-e b)))]
    [else
     (equal?/recur a b stx=?)]))

One way to think about equal?/recur is that it knows how to recur on built-in compound data, and it knows how to determine equality of built-in atomic data.

By supplying a recur-proc, we can customize how atomic data are compared, without having to explicitly handle the recurrence on compound data.

For example, say I want to compare reals approximately. If they are within 0.5, they should be considered equal. But I also want to make the comparison work with vectors, lists, structures containing reals.

Here’s one possible implementation.

#lang racket

(define (approx-= a b)
  (cond
    [(and (real? a) (real? b))
     (<= (abs (- a b)) 0.5)]
    [else (equal?/recur a b approx-=)]))

(approx-= 1 2) ;=> #f
(approx-= 1 1) ;=> #t
(approx-= 0.7 1) ;=> #t
(approx-= (list 0.7 2 "hello") (list 1 2.1 "hello")) ;=> #t
(approx-= (vector 0.7 2 "hello") (vector 1 10 "hello")) ;=> #f
(approx-= (list (vector 0.7)) (list (vector 1))) ;=> #t

1 Like