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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With