I've just been reading up on the sharpsign colon reader macro and it sounded like it had a very similar effect to gensym
Sharpsign Colon: "introduces an uninterned symbol"
Gensym: "Creates and returns a fresh, uninterned symbol"
So a simple test
CL-USER> #:dave
; Evaluation aborted on #<UNBOUND-VARIABLE DAVE {1002FF77D3}>.
CL-USER> (defparameter #:dave 1)
#:DAVE
CL-USER> #:dave
; Evaluation aborted on #<UNBOUND-VARIABLE DAVE {100324B493}>.
Cool so that fails as it should.
Now for the macro test
(defmacro test (x)
(let ((blah '#:jim))
`(let ((,blah ,x))
(print ,blah))))
CL-USER> (test 10)
10
10
CL-USER>
Sweet so it can be used like in a gensym kind of way.
To me this looks cleaner than gensym with an apparently identical result. I'm sure I'm missing a vital detail so my question is, What it it?
GENSYM
is like MAKE-SYMBOL
. The difference is that GENSYM
supports fancy naming by counting up -> thus symbols kind of have unique names, which makes debugging a bit easier when having gensyms for example in macro expansions.
#:foo
is a notation for the reader.
So you have a function which creates these and a literal notation. Note that, when *print-circle*
is true, some kind of identity maybe preserved in s-expressions: #(#1=#:FOO #1#)
.
Generally this is similar to (a . b)
and (cons 'a 'b)
, #(a b)
and (vector 'a 'b)
... One is literal data and the other one is a form which will create ('cons') fresh objects.
If you look at your macro, the main problem is that nested usage of it could cause problems. Both lexically or dynamically.
lexically it could be the same variable, which is rebound.
dynamically, if it is a special variable it could also be rebound
Using a generated symbol at macro expansion time would make sure that different and expanded code would not share bindings.