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
_________________________________________________
For list-related administrative tasks:
http://lists.racket-lang.org/listinfo/users