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
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