Search code examples
lispcommon-lisp

Common Lisp symbol equality


In most of the examples on the Internet, symbol equality is straight-forward:

(eq 'sym 'sym)
t

In my program, I want to compare symbols in a custom package:

(defpackage #:my-package
  (:use    #:common-lisp)
  (:export #:my-function))

(in-package #:my-package)

(defun my-function (value)
  (cond
    ((eq value 'sym)
     (format t "SYM: YES~%"))
    (t
     (format t "SYM: NO~%"))))

(in-package #:common-lisp)

(my-package:my-function 'sym)

But when this code is executed, it displays:

SYM: NO

It seems like the 2 symbols are different:

(eq 'sym 'my-package::sym)
nil

The reason seems easy to understand, a symbol interned in a given package is not equal to a symbol with the same name interned in another package. Fair enough! But what is the idiom to compare 2 symbols, regardless the package?

Should we convert it to a string in a first place and compare strings?

(defpackage #:my-package
  (:use    #:common-lisp)
  (:export #:my-function))

(in-package #:my-package)

(defun my-function (value)
  (cond
    ((string= (symbol-name value) "SYM")
     (format t "SYM: YES~%"))
    (t
     (format t "SYM: NO~%"))))

(in-package #:common-lisp)

(my-package:my-function 'sym)

The result is better, but there is an obvious issue regarding the character case.

How to check that 2 symbols are the same regardless their package?


Solution

  • The usual idiom is string=, which compares the names of symbols without regard to identity.

    For example:

    (eq 'x:a 'y:a) => nil
    (string= 'x:a 'y:a) => t