What's the difference between eq, eql, equal and equalp, in Common Lisp?

What's the difference between eq, eql, equal and equalp, in Common Lisp? I understand that some of them check types, some of them check across types an all that, but which is which? When is one better to use than the others?


Solution 1:

From Common Lisp: Equality Predicates

(eq x y) is true if and only if x and y are the same identical object.

The eql predicate is true if its arguments are eq, or if they are numbers of the same type with the same value, or if they are character objects that represent the same character.

The equal predicate is true if its arguments are structurally similar (isomorphic) objects. A rough rule of thumb is that two objects are equal if and only if their printed representations are the same.

Two objects are equalp if they are equal; if they are characters and satisfy char-equal, which ignores alphabetic case and certain other attributes of characters; if they are numbers and have the same numerical value, even if they are of different types; or if they have components that are all equalp.

Here are some examples from the same page I linked to above:

(eq 'a 'b) is false. 
(eq 'a 'a) is true. 
(eq 3 3) might be true or false, depending on the implementation. 
(eq 3 3.0) is false. 
(eq 3.0 3.0) might be true or false, depending on the implementation. 
(eq #c(3 -4) #c(3 -4)) 
  might be true or false, depending on the implementation. 
(eq #c(3 -4.0) #c(3 -4)) is false. 
(eq (cons 'a 'b) (cons 'a 'c)) is false. 
(eq (cons 'a 'b) (cons 'a 'b)) is false. 
(eq '(a . b) '(a . b)) might be true or false. 
(progn (setq x (cons 'a 'b)) (eq x x)) is true. 
(progn (setq x '(a . b)) (eq x x)) is true. 
(eq #\A #\A) might be true or false, depending on the implementation. 
(eq "Foo" "Foo") might be true or false. 
(eq "Foo" (copy-seq "Foo")) is false. 
(eq "FOO" "foo") is false.


(eql 'a 'b) is false. 
(eql 'a 'a) is true. 
(eql 3 3) is true. 
(eql 3 3.0) is false. 
(eql 3.0 3.0) is true. 
(eql #c(3 -4) #c(3 -4)) is true. 
(eql #c(3 -4.0) #c(3 -4)) is false. 
(eql (cons 'a 'b) (cons 'a 'c)) is false. 
(eql (cons 'a 'b) (cons 'a 'b)) is false. 
(eql '(a . b) '(a . b)) might be true or false. 
(progn (setq x (cons 'a 'b)) (eql x x)) is true. 
(progn (setq x '(a . b)) (eql x x)) is true. 
(eql #\A #\A) is true. 
(eql "Foo" "Foo") might be true or false. 
(eql "Foo" (copy-seq "Foo")) is false. 
(eql "FOO" "foo") is false.


(equal 'a 'b) is false. 
(equal 'a 'a) is true. 
(equal 3 3) is true. 
(equal 3 3.0) is false. 
(equal 3.0 3.0) is true. 
(equal #c(3 -4) #c(3 -4)) is true. 
(equal #c(3 -4.0) #c(3 -4)) is false. 
(equal (cons 'a 'b) (cons 'a 'c)) is false. 
(equal (cons 'a 'b) (cons 'a 'b)) is true. 
(equal '(a . b) '(a . b)) is true. 
(progn (setq x (cons 'a 'b)) (equal x x)) is true. 
(progn (setq x '(a . b)) (equal x x)) is true. 
(equal #\A #\A) is true. 
(equal "Foo" "Foo") is true. 
(equal "Foo" (copy-seq "Foo")) is true. 
(equal "FOO" "foo") is false.


(equalp 'a 'b) is false. 
(equalp 'a 'a) is true. 
(equalp 3 3) is true. 
(equalp 3 3.0) is true. 
(equalp 3.0 3.0) is true. 
(equalp #c(3 -4) #c(3 -4)) is true. 
(equalp #c(3 -4.0) #c(3 -4)) is true. 
(equalp (cons 'a 'b) (cons 'a 'c)) is false. 
(equalp (cons 'a 'b) (cons 'a 'b)) is true. 
(equalp '(a . b) '(a . b)) is true. 
(progn (setq x (cons 'a 'b)) (equalp x x)) is true. 
(progn (setq x '(a . b)) (equalp x x)) is true. 
(equalp #\A #\A) is true. 
(equalp "Foo" "Foo") is true. 
(equalp "Foo" (copy-seq "Foo")) is true. 
(equalp "FOO" "foo") is true.

Solution 2:

Some more notes:

  • Most CL functions implicitly use EQL when no test is specified

  • See also STRING-EQUAL, = and TREE-EQUAL

  • At the core of EQ is usually a pointer comparison

And a rough guide:

To compare against...      Use...

Objects/Structs            EQ

NIL                        EQ (but the function NULL is more concise and probably cheaper)

T                          EQ (or just the value but then you don't care for the type)

Precise numbers            EQL

Floats                     =

Characters                 EQL or CHAR-EQUAL

Lists, Conses, Sequences   EQ (if you want the exact same object)
                           EQUAL (if you just care about elements)

Strings                    EQUAL (case-sensitive), EQUALP (case-insensitive)
                           STRING-EQUAL (if you throw symbols into the mix)

Trees (lists of lists)     TREE-EQUAL (with appropriate :TEST argument)

Note that for efficiency usually EQ >> EQL >> EQUAL >> EQUALP.

Solution 3:

From here and my teacher's slides

eq tests to see if its arguments(represented by the same chunk of computer memory) are same symbol or not.

For Example:

(eq ‘A ‘B) NIL
(eq ‘RAM ‘RAM) T
(eq (cons 'a 'b) (cons a' b')) ; This is because different calls are made for both cons so they will obviously be allocated different memory chunks

eql first tests to see if its arguments satisfy EQ, if not, it tries to see if they are numbers of the same type and values.

For Example:

(eql 4 4.0) NIL
(eql 4 4) T

Now note a difference:

(eq 4.0 4.0) NIL ;Depend upon platform as described in first (accepted)answer
(eql 4.0 4.0) T ;type and value of arguments is same

On some implementations (eq 4.0 4.0) may return true because it is not specified in the standard whether an implementation should keep just one copy of numbers and chars in memory, like it does with symbols).As a rule of thumb don’t use eq on numbers and characters, unless you really know what you’re doing.

equal is a “saner” comparison function. As a rule of thumb, you can think of it as telling you whether two objects look the same (structurally similar, or isomorphic). It is probably the operator you want to use for general equality. It behaves like eql for numbers, characters and symbols, but for lists (conses) and strings it tells if their elements

For Example:

(equal 4 4) T
(equal (+ 2 2) 4) T

Now note a difference

(eql (cons 'a 'b) (cons 'a 'b)) NIL
(equal (cons 'a 'b) (cons 'a 'b)) T ; equal is usually true for things that print the same

equalp is like equal, just more advanced. Comparison of numbers is type insensitive. Comparison of chars and strings is case insensitive.

For Example:

(equalp (cons 'a 'b) (cons 'a 'b)) T ;same as equal

Now note a difference

equal(4 4.0) NIL
equalp(4 4.0) T ; As equalp treats numbers type insensitively