Common Lisp中的未分隔符号

时间:2011-12-02 16:18:08

标签: lisp common-lisp

有几次我遇到了不带符号的概念,但我并不完全清楚它们是什么。

有没有办法实习用(make-symbol)创建的符号?
我可以在不实习的情况下为符号赋值吗? 是否可以重命名符号(实习或未实现)? 还有什么可以用一个未加工的符号做什么?

更新
这段代码中的符号发生了什么?

CL-USER> (defun func ()
           (let ((var 'sym))
             (print (find-symbol "sym"))
             (print var)))
FUNC
CL-USER> (func)

NIL 
SYM 
SYM

我的错误理解是:
1. find-symbol打印为nil,因此符号不是inte 2. var在没有#:的情况下打印sym,这意味着它是实习的

2 个答案:

答案 0 :(得分:8)

未加工的符号主要用作名称或指示符,以避免混乱包或相关任务。

例如:

T1> (find-symbol "T2")
NIL
NIL
T1> (find-symbol "T3")
NIL
NIL
T1> (defpackage t2)
#<Package "T2">
T1> (defpackage #:t3)
#<Package "T3">    
T1> (find-symbol "T2")
T2
:INTERNAL
T1> (find-symbol "T3")
NIL
NIL

正如您所看到的,在第一个t2表单中使用defpackaget1个包中使用#:t3,而在第二个defpackage中使用defpackage可以避免这种情况。这是可能的,因为unintern字符串指示符作为其第一个元素,并且不需要将符号作为指示符来实现。

这些和相关的情况是主要使用未加工符号的地方。您还可以通过使用字符串或关键字来避免污染程序包,但在第一种情况下,可能是使用非默认readtable-case的人的问题,在第二种情况下,您会污染关键字包,这是一些人关心的问题。 (关于这是否真的是一件坏事,有不同的意见。)

然后,在某些情况下,符号会丢失其主页包(例如,通过T1> (defparameter *t2* (find-symbol "T2")) *T2* T1> (import *t2* "T3") T T1> (symbol-package *t2*) #<Package "T1"> T1> (unintern *t2*) T T1> (find-symbol "T2") NIL NIL T1> (symbol-package *t2*) NIL T1> *t2* #:T2 T1> (find-symbol "T2" "T3") #:T2 :INTERNAL T1> (unintern *t2* "T3") T T1> (import *t2* "T3") T T1> *t2* T3::T2 T1> (symbol-package *t2*) #<Package "T3"> ),并且至少显然是未加入的。 (它可能仍然在另一个包中实施。)

T1> (import (make-symbol "T4"))
T
T1> (find-symbol "T4")
T4
:INTERNAL

所以,回答

  

有没有办法实习用(make-symbol)创建的符号?

是的:

T1> (let ((symbol '#:t5))
      (setf (symbol-value symbol) 1)
      (setf (get symbol :foo) :bar)
      (setf (symbol-function symbol) (lambda ()))
      (values (symbol-value symbol)
              (get symbol :foo)
              (symbol-function symbol)))
1
:BAR
#<Anonymous Function #xC829036>
  

我可以在不实习的情况下为符号指定值吗?

是的,当您丢失属性时,它可以通过其名称和包装进行唯一标识,您仍然可以使用其值槽,plist等:

{{1}}
  

是否可以重命名符号(interned或uninterned)?

修改符号名称的后果未定义。

  

用uninterned符号还可以做些什么?

我真的认为它们主要用作包定义中的指示符,但一般的答案是:它们可以在你想要在不使用硬编码字符串的情况下命名并且不想污染任何包的情况下有用

答案 1 :(得分:1)

  1. CL-USER> (intern (string (make-symbol "TEST")))
    TEST
    :INTERNAL 
    
  2. 没有

  3. 没有

  4. 它通常在包声明中用于不污染包的名称空间,其中发生声明(如果使用普通符号)或关键字包,因为defpackage形式的{{ {1}}和:export子句无论如何都会转换为字符串。因此,您可以在函数中使用它,它接受任何内容并将其转换为字符串。更一般地说,未加工的符号可以用作具有名称的唯一对象,而不是其他任何符号。但通常使用关键字符号来实现此目的。