8

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?

hawkeye
  • 34,745
  • 30
  • 150
  • 304
  • 1
    As you are not getting any (real) answers here since three hours: You can try to ask this on "Lambda the Ultimate". You might get kicked out because the list is really about research on programming languages, but the people there can certainly answer your question. http://lambda-the-ultimate.org/ – Eike Aug 15 '10 at 16:40

1 Answers1

7

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
  • 15,783
  • 9
  • 53
  • 76
  • 4
    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 Aug 16 '10 at 00:26
  • 3
    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 Aug 16 '10 at 00:29
  • 2
    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-cl Thanks again, Michal, for clearing things up. – Isaac Aug 16 '10 at 00:51
  • 1
    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 –  Aug 16 '10 at 06:33