Search code examples
lispcommon-lispequalitysymbolshunchentoot

Common Lisp equality on symbol in web application


The following function:

(defun check-for-arrow (x)
  (format t "**~s**~s**~s**~s**"
          (length (string x))
          x
          (eq x '->)
          (and (eq (elt (string x) 0) #\-)
               (eq (elt (string x) 1) #\>))) ; for debug
  (eq x '->))

when called from REPL, with:

(check-for-arrow '->)

prints, with tracing:

0> Calling (CHECK-FOR-ARROW ->) 
**2**->**T**T**
<0 CHECK-FOR-ARROW returned T

Instead, when called inside a Hunchentoot web application, over data read in a form, when called over the symbol '->', prints:

0> Calling (NORMALIZER::CHECK-FOR-ARROW ->) 
**2**->**NIL**T**
<0 NORMALIZER::CHECK-FOR-ARROW returned NIL

The Lisp is Clozure Common Lisp.

Does this depend on a different way of interning symbols ? It is possible to use 'eq' on symbols or I have to transform the arrow in a string and check for string equality?

Thanks.


Solution

  • Common Lisp has packages. Packages are kind of namespaces for symbols.

    Thus one can have many different symbols named "->", each one in a different package.

    Thus normalizer::-> is not necessarily EQ to cl-user::->.

    Symbols can also be NOT interned in a package, thus one can have many different symbols of the same name and no a package.

    CL-USER 2 > '#:->
    #:->
    
    CL-USER 3 > (describe *)
    
    #:-> is a SYMBOL
    NAME          "->"
    VALUE         #<unbound value>
    FUNCTION      #<unbound function>
    PLIST         NIL
    PACKAGE       NIL
    
    CL-USER 4 > '->
    ->
    
    CL-USER 5 > (describe *)
    
    -> is a SYMBOL
    NAME          "->"
    VALUE         #<unbound value>
    FUNCTION      #<unbound function>
    PLIST         NIL
    

    A typical problem:

    One has a function which tests for EQ of something with a certain symbol FOO. The user inputs FOO.

    But how does your Lisp function convert the user input into a symbol? In which package will the symbol be? Remember symbols differ by name AND package. If you don't specify the package, the default is the value of the variable CL:*PACKAGE*. But this variable can have different values at different times.

    Just extend your test function to print the packages of the symbols and you will see the difference.

    CL-USER 7 > (package-name (symbol-package '->))
    "COMMON-LISP-USER"