Search code examples
common-lispequalityland-of-lisp

Understanding data mode in Lisp, why are these expressions not the same?


Currently I am reading "Land of Lisp". In one of the recent code samples the author gave:

> (eq 'fooo 'FoOo)
T

to prove that the symbols are case-insensitive. A few pages later data mode is formally introduced.

However I fail to really understand the following. eq is a function, so its name is case-insensitive as well. Therefore I should be able to do this:

> (eq 'Eq 'EQ)
T

Great. That worked as expected. But what if I put this into a list in data mode? Keep in mind, I am just experimenting with something that's new for me.

> (eq '(Eq) '(EQ))
NIL
> (eq '('Eq) '('EQ))
NIL

Uhm. Okay? Why is that? I would have expected that if I put the same symbol into two lists, that the lists would be considered equal.

Now the question: does that mean that not the contents of the lists are compared, but the list "objects" themselves? What am I missing?


Solution

  • Symbols are Case-Sensitive

    > (eq (print (intern "foo")) (print (intern "FOO")))
    |foo|   ; printed 
    FOO     ; printed
    ==> NIL ; returned
    

    The default reader is Case-Converting

    (eq (read-from-string "foo") (read-from-string "FOO"))
    ==> T
    

    However, you can make the reader case-preserving:

    (let ((*readtable* (copy-readtable)))
      (setf (readtable-case *readtable*) :preserve)
      (eq (read-from-string "foo") (read-from-string "FOO")))
    ==> NIL
    

    Please take a look at

    EQ compares for pointer identity

    Common Lisp provides 4 equality predicates, you should use the right one for your needs:

    (equal '(Eq) '(EQ))
    ==> T
    (equal '('Eq) '('EQ))
    ==> T