Ambrose Bonnaire-Sergeant <[email protected]> writes:
> It's a good question.
>
> Syntax quote is designed for generating code/syntax that is deterministic
> and avoids accidental local name capture.
>
> 1. Automatic namespace qualification helps avoid accidental local name
> capture in macros.
>
> user=> `(let [a# 1
> b# a]
> a#)
> (clojure.core/let [a__48963__auto__ 1
> b__48964__auto__ user/a]
> a__48963__auto__)
>
> The binding for b# shows a common mistake. By namespace qualifying "a" to
> "user/a",
> we don't allow the possibility of accidentally capturing locals.
>
> eg. "a" is not captured in the body
> (let [a 'evil]
> (clojure.core/let [a__48963__auto__ 1
> b__48964__auto__ user/a]
> a__48963__auto__))
>
Ah, yes, this makes sense. So, rewriting the macro without the backtick
looks exactly the same, but can capture locals.
(defmacro remap3 [f & c]
`(map ~f ~@c))
(defmacro remap4 [f & c]
(list* 'map f c))
(let [map (fn [f & c]
(println "evil")
(apply f c))]
(remap3 identity (range 1 10)))
(let [map (fn [f & c]
(println "evil")
(apply f c))]
(remap4 identity (range 1 10)))
Only the latter is evil.
> 2. Automatic namespace qualification helps make code deterministic with
> respect to the namespace of the consumer of a macro.
>
> Syntax quote resolves vars in the namespace the *macro* is defined in.
> This avoids odd situations where different vars are invoked depending
> on which namespace we use the macro.
Yeah, this was what was confusing me, and was breaking my code. I was
using it to generate code, but not in a macro; my code generates a set
of (specific) Java objects from clojure, and I wanted to be able to
reverse the process -- render clojure forms from Java objects; this
was failing because the symbols were always being qualified in the
namespace of the renderer. In essence, I'm using ` for it's syntactic
convienience, rather than in a macro.
> Bottom line: syntax quote is designed for macros by default. All the good
> properties of syntax quote can be avoided using
> combinations of quote, syntax quote and splice.
>
> eg. `~'a
> ;=> a
I have converted my code to use this!
Thanks for the explanation. I was confused.
Phil
--
--
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
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.