This is not to say which languages have the equivalent of GENSYM . Many languages do not have a first-class character data type (with interned and non-reinforced characters), and many of them do not provide code generation objects (macros, ...).
The intern symbol is registered in the package. Uninteresting - no. If the reader (the reader is a Lisp subsystem that accepts text s-expressions as input and return data), sees two interned characters in the same package and with the same name, it assumes that this is the same character:
CL-USER 35 > (eq 'cl:list 'cl:list) T
If the reader sees an uninterrupted character, he creates a new one:
CL-USER 36 > (eq '#:list '
Non-interminable characters are written with #: in front of the name.
GENSYM used in Lisp to create numbered uninterrupted characters, because it is sometimes useful for generating code and then debugging that code. Note that the characters are always new, not eq for anything else. But the name of the symbol may be the same as the name of another symbol. The number gives the reader a key about personality.
Example using MAKE-SYMBOL
MAKE-SYMBOL creates a new uninterrupted character using a string argument as its name.
Let's see how this function generates some code:
CL-USER 31 > (defun make-tagbody (exp test) (let ((start-symbol (make-symbol "start")) (exit-symbol (make-symbol "exit"))) `(tagbody ,start-symbol ,exp (if ,test (go ,start-symbol) (go ,exit-symbol)) ,exit-symbol))) MAKE-TAGBODY CL-USER 32 > (pprint (make-tagbody '(incf i) '(< i 10))) (TAGBODY
The above generated code uses uninterrupted characters. Both #:|start| are actually the same symbol. We will see this if we had *print-circle* up to T , since then the printer would clearly identify identical objects. But here we do not receive this additional information. Now, if you embed this code, you will see more than one start and one exit character, each of which was used in two places.
Example using GENSYM
Now use GENSYM . Gensim also creates a symbol without a symbol. This character is optionally called a string. A number is added (see CL:*GENSYM-COUNTER* ).
CL-USER 33 > (defun make-tagbody (exp test) (let ((start-symbol (gensym "start")) (exit-symbol (gensym "exit"))) `(tagbody ,start-symbol ,exp (if ,test (go ,start-symbol) (go ,exit-symbol)) ,exit-symbol))) MAKE-TAGBODY CL-USER 34 > (pprint (make-tagbody '(incf i) '(< i 10))) (TAGBODY
Now the number is an indicator that two uninterrupted characters #:|start213051| actually the same. When the code is nested, the new version of the start character will have a different number:
CL-USER 7 > (pprint (make-tagbody `(progn (incf i) (setf j 0) ,(make-tagbody '(incf ij) '(< j 10))) '(< i 10))) (TAGBODY #:|start2756| (PROGN (INCF I) (SETF J 0) (TAGBODY #:|start2754| (INCF IJ) (IF (< J 10) (GO #:|start2754|) (GO #:|exit2755|)) #:|exit2755|)) (IF (< I 10) (GO #:|start2756|) (GO #:|exit2757|)) #:|exit2757|)
Thus, it helps to understand the generated code, without the need to include *print-circle* on, which will denote the same objects:
CL-USER 8 > (let ((*print-circle* t)) (pprint (make-tagbody `(progn (incf i) (setf j 0) ,(make-tagbody '(incf ij) '(< j 10))) '(< i 10)))) (TAGBODY #3=#:|start1303| (PROGN (INCF I) (SETF J 0) (TAGBODY #1=#:|start1301| (INCF IJ) (IF (< J 10) (GO #1#) (GO #2=#:|exit1302|)) #2#)) (IF (< I 10) (GO #3#) (GO #4=#:|exit1304|)) #4#)
The Lisp is read above for the reader (a subsystem that reads s-expressions for textual representations), but a little less for the reader.