When this matters
Pick equality by intent, not habit: mathematical equality for numbers, identity-style equality for atoms or the same aggregate object, and deep equality for data structures.
See it run
LISPEX
(list (= 2 2.0) (eqv? 2 2.0) (equal? (list 1 2) (list 1 2)))Observed result
OUTPUT
(#t #f #t)Read the example
= treats exact 2 and inexact 2.0 as the same mathematical number. eqv? preserves the exactness distinction. Two separately constructed lists are not the same object, but equal? sees the same contents.
How to reason about it
eq?andeqv?agree on atoms in this profile and compare aggregates by identity.eqv?andequal?are exactness-sensitive: exact2and inexact2.0are different.equal?descends through pairs, vectors, bytevectors, and strings with cycle detection.
Choose quickly
| Predicate | Use it for | Aggregate behavior |
|---|---|---|
= | numbers with mathematical equality | non-numbers are a domain error |
eq? | atoms and object identity | same aggregate object only |
eqv? | exactness-sensitive atoms and identity | same aggregate object only |
equal? | nested data contents | recursive, cycle-safe structural comparison |
== / != | readable structural aliases | equal? and its negation |
A common mistake
= accepts numbers only; == and != are structural aliases.
Current boundaries
- Procedure equality never compares procedure bodies structurally.
Keep going
Data Types explains which values have identity. Aggregate Procedures shows the constructors that create separate objects.