0

In a Common Lisp program, I want to find a way to generate a new symbol that is not in use in the program at the time. I am aware of the (gensym) function, but this makes symbols that may already be present in the program. I have some understanding that I need to intern the symbol, so I tried this:

(defun new-symbol () (intern (symbol-name (gensym)))) 

Which seems to get halfway to the answer. For instance,

[1]> (new-symbol) G3069 NIL [2]> (new-symbol) G3070 NIL [3]> (defvar a 'G3071) A [4]> (new-symbol) G3071 :INTERNAL 

As you can see, the function seems to recognize that the symbol 'G3071' is already in use elsewhere, but I don't know how to get it to generate a new symbol if that is the case.

1 Answer 1

8

I am aware of the (gensym) function, but this makes symbols that may already be present in the program.

No, it doesn't. It creates symbols that aren't interned in any package. The documentation says (emphasis added):

Function GENSYM

Syntax:

gensym &optional x ⇒ new-symbol

Arguments and Values:

x—a string or a non-negative integer. Complicated defaulting behavior; see below.

new-symbol—a fresh, uninterned symbol.

You can also use make-symbol to create a symbol that's not interned in any package. It's documentation summary (pretty much identical to gensym's):

Function MAKE-SYMBOL

Syntax:

make-symbol name ⇒ new-symbol

Arguments and Values:

name—a string.

new-symbol—a fresh, uninterned symbol.

Regarding your second point:

I have some understanding that I need to intern the symbol, so I tried this:

No, if you want a fresh symbol, then you probably don't want to be interning anywhere. Interning is the process whereby you take a string (not a symbol) and get the symbol with the given name within a particular package. If you call intern with the same symbol name and package twice, you'll get back the same symbol, which is what you're trying to avoid.

CL-USER> (defparameter *a* (intern "A")) *A* CL-USER> (eq *a* (intern "A")) T 

Since gensym generates the name of the fresh symbol using *gensym-counter*, if you take the name from the gensym symbol and intern it somewhere, you could get the same symbol if someone modifies the value of *gensym-counter*. E.g.:

(let ((counter *gensym-counter*) ; save counter value (s1 (gensym))) ; create a gensym (s1) (setf *gensym-counter* counter) ; reset counter value (let ((s2 (gensym))) ; create a gensym (s2) (list s1 s2 (eq s1 s2) (symbol-name s1) (symbol-name s2) (string= (symbol-name s1) (symbol-name s2))))) ; (#:G1037 #:G1037 NIL ; different symbols ; "G1037" "G1037" T) ; same name 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.