> As a clojure fan, I think this is a really well balanced and fair assessment of clojure.
Thanks for the kind words. I tried to keep my biases out of it as much as possible and tried to avoid making it too ranty. And on the whole, I like Clojure; it's just not really my first choice as far as Lisps go.
> It's a bit surprising they didn't get into the whole "hygenic macro" business, which seems like the most obvious differentiator between the two languages to me.
I debated including a bit about macros, but in the end decided that this would be a bit too in-depth. Clojure uses namespaces in a somewhat clever way to work around the bulk of the hygiene issues you get in CL with defmacro, but the macro system itself is rather uninteresting. I think their custom syntax for gensym is a nice touch, even though it's yet more syntax.
Scheme's macro system is very advanced and relatively complicated indeed, and the R5RS/R7RS standard system is only pattern matching/rewriting based.
Maybe I'll do a separate piece on the macro system if people are really interested.
Hey, I also enjoyed the article... and would definitely be interested in reading more about macros.
But unrelated to that, I wanted to comment on this observation:
> In my current project, it takes almost 30 seconds to boot up a development REPL. Half a minute!
I work mostly with JVM languages and the JVM startup nowadays is actually very fast for a VM, under 100ms for your code in main to be running from a cold start. 30 seconds to boot is completely unheard of in my experience. If whatever you're using is open source, I wouldn't mind having a look to figure out what the problem may be.
That's Clojure, it compiles .clj files on demand into jvm .class when you require them. Here probably his user.clj is loading the whole application. You can do some dynamic things to delay the loading/compiling until after your REPL starts, so that you get a repl in 1-2 seconds. https://gist.github.com/dustingetz/a16847701c5ad4a23b304881e... In production you would ahead-of-time compile.
I also shaved 35% of my "time to CIDER REPL" by passing a few parameters to the JVM (-client, -Xverify:none, plus two tieredcompilation-related settings I copy/pasted).
I’m curious what you mean by “ Clojure uses namespaces in a somewhat clever way to work around the bulk of the hygiene issues you get in CL with defmacro”. CL and Clojure are, in my experience, basically equivalent here: CL’s solution to hygiene issues is a combination of packages (“namespaces”), gensym. The main difference is that, as a Lisp-2, hygiene issues tend to be easier to avoid because you can’t use LET to shadow functions (which, in my experience writing Clojure, is the most common problem: accidentally declaring a variable called “name”, or similar).
Because Clojure relies so heavily on namespaces, almost all identifiers in a macro's output are going to be fully namespaced already, especially because syntax-quote does this expansion already. Therefore, unintended variable capture is highly unlikely.
> And on the whole, I like Clojure; it's just not really my first choice as far as Lisps go
... Yet ;)
I think reading your article, familiarity seemed to be the source of a lot of your pain points. I wonder if the more you use it, to the point it becomes as familiar as Scheme, if you'd change your choice. Maybe not, but I think that's a possibility.
I've wrapped my head around the CL/Clojure sort of macro but never really grasped the essence of Scheme's hygenic system, always happy to read more about Lisp macros.
> [...] the R5RS/R7RS standard system is only pattern matching/rewriting based. Maybe I'll do a separate piece on the macro system if people are really interested.
I'd like to throw in a "me too" too.
I'm comfortable enough using Scheme's syntax-rules macros, and I've seen a couple examples where syntax-case macros do something beyond, but I'd love a walkthrough of how syntax-rules maintains hygiene and a concise explanation of how Clojure nearly accomplishes the same goal with namespaces.
Thanks for the kind words. I tried to keep my biases out of it as much as possible and tried to avoid making it too ranty. And on the whole, I like Clojure; it's just not really my first choice as far as Lisps go.
> It's a bit surprising they didn't get into the whole "hygenic macro" business, which seems like the most obvious differentiator between the two languages to me.
I debated including a bit about macros, but in the end decided that this would be a bit too in-depth. Clojure uses namespaces in a somewhat clever way to work around the bulk of the hygiene issues you get in CL with defmacro, but the macro system itself is rather uninteresting. I think their custom syntax for gensym is a nice touch, even though it's yet more syntax.
Scheme's macro system is very advanced and relatively complicated indeed, and the R5RS/R7RS standard system is only pattern matching/rewriting based.
Maybe I'll do a separate piece on the macro system if people are really interested.