clojure - (gensym) is always unique, `(symb#) is not -- why? -
if write macro uses symb#
shortcut create gensym bound global variable, exact same symbol gets generated on , over. however, functions correctly if call gensym
manually. simple examples:
(defmacro indirection [name & body] `(do (def name# ~@body) (defn ~name [] name#))) (indirection foo 3) (foo) ; ⇒ 3 (indirection goo 5) (goo) ; ⇒ 5 (foo) ; ⇒ 5
the problem apparent if use macroexpand
:
(macroexpand '(indirection foo 3)) (do (def name__2863__auto__ 3) (clojure.core/defn foo [] name__2863__auto__)) (macroexpand '(indirection foo 3)) (do (def name__2863__auto__ 3) (clojure.core/defn foo [] name__2863__auto__))
this problem goes away if call gensym
long way:
(defmacro redirection [name & body] (let [rename (gensym)] `(do (def ~rename ~@body) (defn ~name [] ~rename)))) (redirection koo 3) (koo) ; ⇒ 3 (redirection moo 5) (moo) ; ⇒ 5 (koo) ; ⇒ 3
so, why difference? missing?
syntax quoting `
reader macro; form follows transformed reader (which translates text clojure forms) prior evaluation. means symbol ending in #
within syntax-quoting translated autogenerated symbol once, when text first read; autogenerated symbol inserted directly macro definition, , appears verbatim in macroexpanion every time macro invoked. can illustrated @ repl:
user=> `(foo bar#) (user/foo bar__2288__auto__) user=> `(foo bar#) (user/foo bar__2291__auto__)
the typical use case auto-gen'ed symbols #
define local variables inside quoted let
or fn
form. there, not matter same symbol re-used multiple macro invocations; needs unique within each invocation. instance:
(defmacro indirection [name body] `(let [name# ~body] (defn ~name [] name#)))
Comments
Post a Comment