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
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 unintern
ing, 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.