Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differences between Sharpsign Colon and Gensym

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?

like image 868
Baggers Avatar asked Feb 02 '15 09:02

Baggers


1 Answers

Every time the macro is expanded, it will use the same symbol.

(defmacro foo () `(quote #:x))
(defmacro bar () `(quote ,(gensym)))

(eq (foo) (foo)) => t
(eq (bar) (bar)) => nil

Gensym will create a new symbol every time it is evaluated, but sharp colon will only create a new symbol when it is read.

While using sharp colon is unlikely to cause problems, there are a couple rare cases where using it would lead to nearly impossible to find bugs. It is better to be safe to begin with by always using gensym.

If you want to use something like sharp colon, you should look at the defmacro! macro from Let Over Lambda.

like image 166
malisper Avatar answered Nov 05 '22 14:11

malisper