Working with Strings

Issue: EQL is often the default, but it won't compare strings, lists and compound objects.

(find "hello" (list "foo" "hello"))

Will return nil. VS

(find "hello" (list "foo" "hello") :test #'string=)

Will return the string.

Why? EQL is true for

  • Same identical objects (pointers)
  • or numbers of the same type (int and int, not int and float)
(eql "hello" "hello") ;; NIL
(eql 2 2.0)           ;; NIL
(eql 2 2)             ;; T

EQ is the lowest level one.

  • Only true for identical objects: same pointers. Only reliable for:
    • keywords
    • symbols
(eq :a :b)
(eq 'a 'b)

For numbers, characters... Unspecified (so it might be true for you, false for me)

EQ < EQL < EQUAL (in terms of utility)

EQUALP is not as strict on the types.

(equalp 2 2.0)        ;; T
(= 2 nil)             ;; ERROR, so to be defensive use EQUAL or EQUALP

Strings: STRING=, EQUAL |

  • and EQUALP for case insensivity
  • and string-equal to specify :start and :end indexes.
(string= "hello" "hello") ;; T
(string= "hello" "HELLO") ;; NIL
(equal "hello" "HELLO")   ;; NIL
(equalp "hello" "HELLO")  ;;; T

;; compare in substrings:
(string-equal "hello" "hello world" :end2 5)  ;; T
  • see the Common Lisp cookbook and Vindarel CL str library for more information. Also check out the generic cl library.