LISP - 制作新的独特符号

时间:2015-11-10 21:03:23

标签: common-lisp symbols

在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'已在其他地方使用过,但如果是这种情况,我不知道如何让它生成新的符号。

1 个答案:

答案 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