Search code examples
macrosclojurelispschemehygiene

What is it about a single namespace that leads to unhygienic macros? (in LISP)


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?


Solution

  • 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#.