1

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?

1
  • Note that string= and several other string-related functions accept string designators as parameters: strings, symbols (denoting their name), and characters. Commented Sep 9, 2022 at 17:15

2 Answers 2

5

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 
Sign up to request clarification or add additional context in comments.

Comments

2

I think you are confused about what 'being the same symbol' means.

Two symbols are the same symbol iff they are eq, which means that if they are not eq they are not the same symbol. In particular if two symbols have home packages which are different (again: not eq) they are not the same symbol.

If you want to know if two symbols have the same name then simply compare their symbol-names, as strings. But two symbols which merely have the same name are not necessarily the same symbol (for instance (eq '#:foo '#:foo) is false).

There are cases where it is useful to know whether two symbols have the same name (for instance the loop macro must do this so that (loop for ...) and (loop :for ...) mean the same thing) but these cases are fairly rare.

If what you want to do is know if two symbols have the same names you quite likely should be using strings instead.

If what you actually want to know is whether two symbols accessed from different packages are really the same symbol (so (eq 'x:foo 'y:foo), say) then eq is the appropriate test, and understanding the package system also helps.

2 Comments

> I think you are confused about what 'being the same symbol' means. Not any more than the loop macro, though.
@Kaz: I mentioned loop. But I think loop treats symbols with the same name as serving the same semantic purpose, rather than as 'being the same'. In particular I think it's worth, when writing CL, to use the spec's notion of 'being the same' which means (unless a predicate is specified) 'being the same under eql'. I know you know this, but I am not sure the person asking the question does.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.