Lisp defines 4 generic equality predicates. In order of "strictness" they are:
eq takes 2 objects as arguments and returns t if they are identical
Integers and Characters have the same symbol-name and value, so when comparing Integers and Characters, whilst it may appear eq is testing for value equality, it is in fact testing for object equality.
eq is fast but is only safe to use when the types (i.e. classes) of the objects being tested are known in advance
GDL-USER> ((eq 1 1)T
GDL-USER> (eq #\a #\a)T
Floats, lists, and strings however are just pointers to the actual objects containing the value in memory, so eq will generally return NIL if either of the objects being tested is a float, list or string. This is because two floats, lists, or strings, even though they may appear to be identical, typically are existing in two different places in memory.
GDL-USER> (eq 1.0 1.0)NIL
GDL-USER> (eq "a" "a")NIL
GDL-USER> (eq (list 1 2 3) (list 1 2 3))NIL
GDL-USER> (eq 1 1.0)NIL
eql behaves as eq except it guarantees to consider 2 objects of the same class representing the same numeric or character value to be equal
GDL-USER> (eql 1.0 1.0)T
GDL-USER> (eql "a" "a")NIL
GDL-USER> (eql (list 1 2 3) (list 1 2 3))NIL
GDL-USER> (eql 1 1.0)NIL
equal behaves as eql except different objects may be considered equivalent if their values look the same. This is particularly useful when testing for equality between two strings or two lists
GDL-USER> (equal "a" "a")T
GDL-USER> (equal (list 1 2 3) (list 1 2 3))T
GDL-USER> (equal 1 1.0)NIL
GDL-USER> (equal "A" "a")NIL
GDL-USER> (equal (list 1 2 3) (list 1 2 3.0))NIL
equalp behaves as equal, except numbers are considered equal if they are mathematically equal, and string equality is not case-sensitive
GDL-USER> (equalp 1 1.0)T
GDL-USER> (equalp "A" "a")T
GDL-USER> (equalp (list 1 2 3) (list 1 2 3.0))T
In addition to the above, Lisp defines specific equality tests (predicates) for numbers and strings
- < - less than
- <= - less than or equal
- = - equal
- >= - greater than or equal
- > - greater than
- /= - not equal
All of these functions take one or more arguments, and with the exception of /=, all make their comparisons between consecutive pairs. With /=, it compares all posible combinations of the arguments
GDL-USER> (> 5 4 3)T
GDL-USER> (> 5 4 5)NIL
GDL-USER> (/= 1 2 3 4)T
GDL-USER> (/= 1 1 4 1)NIL
Specific tests for number values are also avaliable
- zerop - the number is zero
- plusp - the number is greater than zero
- minusp - the number is less than zero
When comparing Float numbers, it is better to use the GendL functions near-to? and near-zero?. These return T if the two arguments are within *ZERO-EPSILON* of each other
string comparison is similar number comparison, except there is one variant (the first shown below) which is case-sensitive and one (the second) which is case-insentitive. These functions accept two string arguments.
- string<, string-lessp - one string less than another
- string=, string-equal - one string equal to another
- string>, string-greaterp - one string greater than another
- string/=, string-not-equal - strings are not equal
These functions also have keyword inputs (:start1 :end1 :start2 and :end2) to enable substrings of the supplied strings to be compared
Finally, Lisp defines predicates to test for object type
- numberp - returns T if the object is a number.
- floatp - returns T if the object is a float.
- stringp - returns T if the object is a string.
- characterp - returns T if the object is a character.
- listp - returns T if the object is a list.