LISP - 制作新的独特符号

Wol*_*ane 0 symbols common-lisp

在Common Lisp程序中,我想找到一种方法来生成当时未在程序中使用的新符号.我知道(gensym)函数,但这会产生可能已存在于程序中的符号.我有一些理解,我需要实习符号,所以我尝试了这个:

(defun new-symbol () (intern (symbol-name (gensym))))
Run Code Online (Sandbox Code Playgroud)

这似乎得到了答案的一半.例如,

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

正如您所看到的,该函数似乎认识到符号'G3071'已经在其他地方使用,但我不知道如果是这样的话,如何生成新符号.

Jos*_*lor 8

我知道(gensym)函数,但这会产生可能已存在于程序中的符号.

不,它没有.它会创建未在任何包中实现的符号.文件说(重点补充):

功能GENSYM

句法:

gensym&optionalx⇒new-symbol

论点和价值观:

x-a string或非负整数.复杂的违约行为; 见下文.

符号 - 一个新鲜的,没有符号的符号.

您还可以使用make-symbol创建一个未在任何包中实现的符号.它的文档摘要(几乎与gensym的相同):

功能MAKE-SYMBOL

句法:

make-symbolname⇒new-symbol

论点和价值观:

name-一个字符串.

符号 - 一个新鲜的,没有符号的符号.

关于你的第二点:

我有一些理解,我需要实习符号,所以我尝试了这个:

不,如果你想要一个新的符号,那么你可能希望在任何地方实习.Interning是一个过程,您可以使用字符串(而不是符号)并在特定包中获取具有给定名称的符号.如果您使用相同的符号名称和包裹两次调用实习生,您将获得相同的符号,这是您要避免的.

CL-USER> (defparameter *a* (intern "A"))
*A*
CL-USER> (eq *a* (intern "A"))
T
Run Code Online (Sandbox Code Playgroud)

由于gensym使用*gensym-counter*生成新符号的名称,如果从gensym符号中取名称并在某处实习,如果有人修改了*gensym-counter*的值,则可以得到相同的符号.例如:

(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
Run Code Online (Sandbox Code Playgroud)