11

I've heard that Clojure macros are easier to write but not as reliable as Racket's hygienic macros. My question has 2 parts:

  1. How does gensym differ from hygienic macros?
  2. What do Racket macros provide that Clojure's don't? (be it safety, composability, or anything)
  • 2
    Hygienic macros are macros whose expansion is guaranteed not to cause the accidental capture of identifiers. The general problem of accidental capture was well known within the Lisp community prior to the introduction of hygienic macros. Macro writers would use language features that would generate unique identifiers (e.g., gensym) or use obfuscated identifiers in order to avoid the problem. Hygienic macros are a programmatic solution to the capture problem that is integrated into the macro expander itself. en.wikipedia.org/wiki/Hygienic_macro – Robert Harvey Jan 12 '16 at 4:37
  • 3
    Because [Racket's] hygienic macro system has deep knowledge of how your macro works, your macro is extremely well-integrated into the environment: syntax highlighting works correctly, automatic variable renaming works correctly, cross-referencing works correctly, and so do all the other slick [Racket] IDE features. In other words, hygiene doesn't just protect you against simple bugs such as variable capture—it allows your code to formally analyzed by tools that simply could not exist for Common LISP. randomhacks.net/2002/09/13/hygienic-macros – Robert Harvey Jan 12 '16 at 5:43
6

The advantage of hygienic macros is not one of language capability -- you can write macros that have good hygiene using gensym and careful quoting/unquoting at the right times. However, hygienic macros ensure your macros have good hygiene. In that respect, it's a bit like type-checking.

There may also be tooling advantages to hygienic macros. Most hygienic macro systems impose tight controls on what your macro does and how it does it (e.g., you can't execute arbitrary code when a macro defined by Scheme's syntax-case is expanded). This can make it easier to write programs that "understand" your macro and can provide additional tooling support.

On the other hand, there are some cases where unhygienic macros may be useful. For example, if you actually want to capture a binding for a specific variable (e.g., anaphoric macros) then I think you're out of luck if you only have hygienic macros.

  • 2
    gensym prevents the macro from accidentally messing with the macro user, but does not prevent the macro user from messing with the macro. For example, a macro user can redefine if or something like that. (The question "why would anybody do that" is irrelevant. This is a simple example that demonstrates that it's possible, and it's tricky to reason about non-hygienic macros) – Phil Nov 4 '16 at 3:08
  • 2
    Unhygienic macros are certainly useful. I'm not sure about Scheme, but Racket has lots of "hygiene-bending" operations. The language's macros are hygienic by default. They just make you very conscious when you break hygiene. – Phil Nov 4 '16 at 3:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.