All equals are not created equal EQ? is the most discriminating test of equality. If EQ? can't tell the difference between two things, then nothing else in Scheme can either. Pairs are EQ? only if they share the same box and pointer structure. The behavior of EQ? on numbers is not defined -- it's implementation dependent. You shouldn't use EQ? for numbers. = works only on numbers. It isn't a "true predicate." It generates errors when given something that isn't a number. EQV? is "the usual" test for equality of atomic items. It uses EQ? for symbols and booleans, = for numbers, char=? for characters, etc. For procedures it isn't well defined (but uses EQ? in MIT Scheme). For pairs it uses EQ?, so it will return true only if both items share the same box and pointer structure. For strings, uses EQ?. EQUAL? tests "whether they print the same". It uses EQV? for everything except pairs. It recurses on the CAR and CDR. See pp.13-15 of the Revised4 Report on the Algorithmic Language Scheme for a complete description of eq?, eqv? and equal?. Examples: EQ? (eq? 'a 'a) => #t (eq? 100000000 100000000) => unspecified (probably #f) (eq? car car) => #t (eq? '() '()) => #t (eq? (list 'a) (list 'a)) => #f (let ((x '(a))) (eq? x x)) => #t EQV? (eqv? 'a 'a) => #t (eqv? 100000000 100000000) => #t (eqv? '() '()) => #t (eqv? (cons 1 2) (cons 1 2)) => #f (let ((a (cons 1 2))) (eqv? a a)) => #t EQUAL? (equal? 'a 'a) => #t (equal? 2 2) => #t (equal? "abc" "abc") => #t (equal? '(a) '(a)) => #t (equal? '(a (b) c) '(a (b) c)) => #t (modified from Holly Yanko's recitation notes)