在Common Lisp程序中,我想找到一种方法来生成当时未在程序中使用的新符号。我知道(gensym)函数,但这会产生可能已存在于程序中的符号。我有一些理解,我需要实习符号,所以我尝试了这个:
(defun new-symbol () (intern (symbol-name (gensym))))
这似乎得到了答案的一半。例如,
[1]> (new-symbol)
G3069
NIL
[2]> (new-symbol)
G3070
NIL
[3]> (defvar a 'G3071)
A
[4]> (new-symbol)
G3071
:INTERNAL
正如您所看到的,该功能似乎认识到了符号' G3071'已在其他地方使用过,但如果是这种情况,我不知道如何让它生成新的符号。
答案 0 :(得分:8)
我知道(gensym)函数,但这会产生可能已存在于程序中的符号。
不,它没有。它会创建未在任何包中实现的符号。文件说(重点补充):
Function GENSYM
<强>语法:强>
gensym&amp;可选x⇒新符号
参数和值:
x-a string或非负整数。复杂的违约 行为;见下文。
new-symbol- 一个新鲜的,没有内嵌的符号。
您还可以使用make-symbol创建一个未在任何包中实习的符号。这是文档摘要(与 gensym 非常相似):
Function MAKE-SYMBOL
<强>语法:强>
制作符号名称⇒新符号
参数和值:
name-a string。
new-symbol- 一个新鲜的,没有内嵌的符号。
关于你的第二点:
我有一些理解,我需要实习符号,所以我尝试了这个:
不,如果你想要一个新的符号,那么你可能不想要在任何地方实习。实习是一个过程,您可以使用字符串(而不是符号)并在特定包中获取具有给定名称的符号。如果您使用相同的符号名称和包裹两次调用实习生,您将返回相同的符号,这是您要避免的。
CL-USER> (defparameter *a* (intern "A"))
*A*
CL-USER> (eq *a* (intern "A"))
T
由于 gensym 使用 * gensym-counter * 生成新鲜符号的名称,如果您从 gensym 符号中取名称,在某个地方实习,如果有人修改了 * 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