[racket] Again on bindings visibility in eval
On 07/15/2011 05:40 AM, Mark Engelberg wrote:
> I would like to better understand how Clojure's mitigation strategy is
> insufficient. Since Eli's document is all about the while macro,
> let's look at Clojure's while macro.
>
> (defmacro while [test& body]
> `(loop []
> (when ~test
> ~@body
> (recur))))
>
This doesn't work at the REPL as such since clojure.core/while cannot be
redefined (unlike in Racket) but let's assume you typed my-while or
went through the namespace magic to have while refer to something you can change.
> What is broken about this? I tried breaking it in a way comparable to
> what Eli did in his document, e.g., binding every keyword/variable in
> the macro to something non-sensical, but it didn't break. Here's the
> comparable Clojure code to what Eli did:
> (def x (atom 2))
> (let [loop 5 when 2 test 4 body 3 recur 4]
> (while (< @x 10)
> (println @x)
> (reset! x (inc @x))))
Quasi-quote is magical in Clojure and replaces symbols in the pattern by
their equivalents in the global namespace.
Compare:
user=> `while
clojure.core/while
user=> 'while
while
So the macro is probably fine as-is, but this relies
on you having stayed within the confines of the quasi-quote sublanguage.
As soon as you start manipulating code using quote and cons you run back
in all the usual issues.
BTW, this "feature" appears to be quite undocumented, I found it
out by experimentation.
So it is anybody's guess what happens if you have macro-expanders calling
functions in different namespaces which use quasiquote, or even macros
which expand into macros with multiple levels of quasi-quote.
Stephan