The Scheme reports do not require that the procedure equal? terminates when the input is looped, as can happen with set-car! and such. Below is a simple implementation of an Equal? that is guaranteed to return #t or #f even for looped structures. This is possible in OCaml but not in a general way. See list compare and tree compare.
This algorithm occurs in the two level grammar for Algol 68 where it is used to test for equivalence of recursive types.
(define (Equal? a b) (let e ((a a)(b b)(h '()))(or (let be ((s h))(and (pair? s) (or (and (eq? a (caar s))(eq? b (cdar s)))(be (cdr s))))) (let ((h (cons (cons a b) h))) (or (eqv? a b) (and (pair? a)(pair? b) (e (car a)(car b) h)(e (cdr a)(cdr b) h)) (and (vector? a)(vector? b) (let ((k (vector-length a)))(and (= k (vector-length b)) (let x ((n (- k 1))) (or (negative? n) (and (e (vector-ref a n)(vector-ref b n) h) (x (- n 1))))))))))))) ; Trivial tests (define a '(2 3 4)) (set-cdr! (cddr a) a) ; (2 3 4 2 3 4 ...) (define b '(2 3 4 2 3 4)) (set-cdr! (cddr (cdddr b)) b) ; b -> (2 3 4 2 3 4 2 3 4 ...) (Equal? a b) ; -> #t (define c '(2 2 2)) (define d '(2 2 3)) (set-cdr! (cddr c) c) (set-cdr! (cdr d) d) (Equal? c d) ; -> #t ; both print as (2 2 2 2 2 ...) (Equal? c (cdr c)) ; -> #t