|
|
|
|
|
by saurik
5013 days ago
|
|
There seemed to be some confusion during the question and answer segment regarding the relative hygiene of macros in Clojure near the end of the motivation and design talk; while it was totally off-topic for the video (and it thereby made sense to take it offline), I personally wish I had been around afterwards to ask the guy who seemed so adamant that syntax-case was fundamentally better than the Clojure solution (which he claimed didn't do it correctly) why that was the case. I'm totally willing to believe it, but based on my understanding (which sadly is somewhat limited for Scheme, but fairly in-depth for Clojure) it isn't intuitive to me: it would seem like the way you escape hygiene in Clojure (which by default achieves correct hygiene by attaching namespaces to symbols read for macros or inside of quasi-quote) is quite similar in semantics--but simpler in practice due to being exceedingly less verbose--than using syntax->datum and datum->syntax. |
|
Hygiene is (roughly speaking) about getting scope right by default but has never been about forcing it on the programmer. Moreover, there are two components to it, only one of which is easy to achieve in an unhygienic system. It's easy to ensure your macro renames introduced /bindings/ by using gensym. But if your macro introduces /references/ to existing variables, it's very hard to protect against those references getting captured at the site where clients call your macro.
I believe in Clojure they get around this for some cases by letting you fully qualify a reference to a library binding, for example. But what if your macro wants to refer to a variable that's local to it? Such as an unexported library function, or simply a local variable. Again, I don't know if Clojure has an answer to this.
One concrete example: write a `define-inline` macro-defining-macro. At the call site, a user might write
In an unhygienic system, they should first of all fully-qualify the `+` to be safe (yuck!) whereas a hygienic system just gets that right by default. But more critically, how can they be sure that some client of `foo` won't write: Not only will that break, it's not clear how to fix it. A hygienic system gets this right.I do agree that the state of the art in hygienic macros is too complex. I just haven't seen another system that makes this kind of thing work. But I would like to experiment with Clojure's macros more to see if they have an answer.
Dave