Uninterned symbols in Common Lisp

2019-04-24 09:28发布

Several times I came across the notion of uninterned symbols, but I am not entirely clear about what they are.

Is there a way to intern a symbol created with (make-symbol)?
Can I assign a value to a symbol without interning it?
Is it possible to rename a symbol (interned or uninterned)?
What else can one do with an uninterned symbol?

Update:
What is happening with symbols in this piece of code?

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

NIL 
SYM 
SYM

My incorrect understanding is:
1. find-symbol prints nil, so the symbol is not intered
2. var prints sym without #: in the beginning which means it is interned

2条回答
放我归山
2楼-- · 2019-04-24 09:59

Uninterned symbols are mostly used as names or designators to avoid cluttering packages, or for related tasks.

For example:

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

As you can see, using t2 in the first defpackage form interns it in package t1, while using #:t3 in the second defpackage avoids this. This is possible, because defpackage takes a string designator as its first element, and a symbol doesn't need to be interned to function as a designator.

These and related situations are where uninterned symbols are mostly used deliberately. You could also avoid polluting the package by using a string or a keyword, but in the first case, there may be problems with people using other than the default readtable-case, and in the second case you would pollute the keyword package, which some people care about. (There are different opinions as to whether this really is such a bad thing or not.)

Then, there are situations where a symbol loses its home-package (by uninterning, for example) and becomes at least apparently uninterned. (It may still be interned in another package.)

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">

So, the answer to

Is there a way to intern a symbol created with (make-symbol)?

is yes:

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

Can I assign a value to a symbol without interning it?

Yes, while you're losing the property that it can be uniquely identified by its name and packagage, you can still use its value slot, plist, etc.:

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>

Is it possible to rename a symbol (interned or uninterned)?

The consequences of modifying a symbol's name are undefined.

What else can one do with an uninterned symbol?

I really think they're mostly used as designators in package definitions, but to the general answer would be: They can be useful in situations where you want to name things without using hardcoded strings and don't want to pollute any package.

查看更多
倾城 Initia
3楼-- · 2019-04-24 10:22
  1. Yes

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

  3. No

  4. It is usually used in package declaration not to pollute the namespace of the package, in which the declaration takes place (if an ordinary symbol was used) or keyword package, because entries in defpackage form's :export and :use clauses are converted to string anyway. So, you can use it in functions, which accept anything and convert it to strings. More generally, uninterned symbols can be used as unique objects with a name and nothing else. But usually keyword symbols are used for such purpose.

查看更多
登录 后发表回答