Hi,
Am 25.12.2011 um 11:37 schrieb Razvan Rotaru:
> Consider following code:
>
> (defprotocol WithOptions
> (getOptions [this] "All options")
> (getOption [this option] "One option"))
>
>
> (defn- gen-proxy [klass opts]
> `(proxy [~klass WithOptions] []
> (getOptions [~'_] ~opts)
> (getOption [~'this x#] ((getOptions ~'this) x#))))
>
>
> The gen-proxy functions is a helper which is used in macros. The code
> works, as far as I can tell, but there's one thing that intrigues me:
> the usage of unquote/quote is necessary (~'_ and ~'this). I assume it
> has something to do with macros qualifying symbols with the current
> namespace. I am yet to fully understand the mechanism here, but my
> question for the moment is whether this kind of construct is idiomatic
> in clojure. Or is there another way to introduce symbols in macros?
The reason for this is macro hygiene. The ~' is required to introduce a
capturing binding into the context of the macro. That is, it shadows a possible
this usage in opts. These is usually not what you want and should be avoided.
Nevertheless it is possible to do it via ~', which is sufficiently ugly to make
you consider whether it's really what you want to do. The normal way to
introduce symbols is via the # notation to generate a new symbol, which does
not clash with user code.
user=> (defmacro oops [& body] `(let [~'murksi 5] ~@body))
#'user/oops
user=> (let [murksi 7] (oops (println murksi)))
5
nil
BTW: this is implicit in proxy. So you don't have to provide it.
(defn- gen-proxy [klass opts]
`(proxy [~klass WithOptions] []
(getOptions [] ~opts)
(getOption [x#] ((getOptions ~'this) x#))))
Note, how ~'this is still required. That's just one more reason, why you don't
want to capture symbols: it makes macro writing harder. Compare to reify:
(defn- gen-reify [opts]
`(reify
WithOptions
(getOptions [this#] ~opts)
(getOption [this# x#] ((getOptions this#) x#))))
Having this given explicit in the definition makes writing macros simpler.
Sincerely
Meikel
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en