views:

190

answers:

1

Some claim that a single namespace in LISP leads to unhygienic macros. http://community.schemewiki.org/?hygiene-versus-gensym

http://www.nhplace.com/kent/Papers/Technical-Issues.html

What precisely is it about having single, dual or multiple namespaces that leads to macro hygiene?

+4  A: 

Lisp-2 means you have two namespaces: one for functions, one for the other stuff.

This means you're less likely to rebind a function value (or var value) in a macro, unwittingly.

In Lisp-1, since there's one namespace, you're (statistically, but not practically) twice as likely to hit an existing definition.

In reality, Lisp-1s have hygiene covered with things like gensym and Scheme's confusingly wide array of syntax-structure-like macros that keep things hygienic.

As best I can tell, the issue is mostly a straw-man argument: it's only an issue in the poorer or older implementations.

Clojure offers hygienic macros through gensym or the reader macro myvar# (the # is essentially gensym).

And you don't have to worry about local scope rebinding your function in your macros, either: Clojure is all clean:

user=> (defmacro rev [xs] `(reverse ~xs))
#'user/rev
user=> (rev [1 2 3])
(3 2 1)
user=> (let [reverse sort] (rev [1 2 5 3 6]))
(6 3 5 2 1)

And here's some variable hygiene:

user=> (defmacro k [] (let [x# "n"] x#))
#'user/k
user=> (k)
"n"
user=> (let [x "l"] (k))
"n"
user=> (let [x "l"] (str (k) x))
"nl"

Notice our sexy gensym'd x#.

Isaac Hodes
Actually the `rev` macro works mostly because of how Clojure automatically resolves symbols introduced by literals in syntax-quote forms coupled with the fact that namespace-qualified symbols may not name locals (the `reverse` actually becomes `clojure.core/reverse` in the expansion; `(let [reverse :foo] (rev ...))` is not a problem, because the `rev` form's expansion never mentions `reverse` -- it mentions `clojure.core/reverse`). This is, as far as I know, an innovative contribution of Clojure to the macro hygiene debate.
Michał Marczyk
Of course `gensym`s are absolutely crucial here, but a package system (package is CL lingo; that's what the word "namespace" is used for in Clojure land) is fundamental to non-hygienic macro sanity as well and Clojure's autoresolving is a particularly smart way of squeezing it to be of as much help as possible.
Michał Marczyk
I completely forgot that the syntax-quote fully resolves the symbols it encloses: thank you for that! I think my answer is correct, but that is an important/interesting thing to note. I actually took advantage of that in an earlier iteration of my answer to this question: http://stackoverflow.com/questions/3480377/clojure-namespace-management-is-there-a-way-to-save-and-restore-the-state-of-clThanks again, Michal, for clearing things up.
Isaac Hodes
Excellent set of comments. May I also add this thread on clojure mailing list where Rich Hickey explains the uniqueness of Clojure macros: http://groups.google.com/group/clojure/msg/7c10f217778ec877
Ramakrishnan Muthukrishnan