A few of my friends and I are working on a new platform and we want to build it in lisp. The main attraction are macros. We all use Common Lisp but I want to explore the option
Clojure Macros have some advantages:
May be your friend is referring Clojure macro system is "weaker" in the sense that Clojure as of now doesn't support "reader macros", but that doesn't mean that the macro system is weaker as reader macros can make things really really complex as far as my understanding of using them is concerned.
I also wont suggest that you should take macros as the main attraction. They are powerful but when you are attracted to some specific technique you start applying it everywhere even though there is a much simpler technique available (in macro case the simpler technique is functions).
Another important thing you should consider is the "platform" that you want to target as Clojure supports JVM and along with all the tools that are there for JVM platfom.
I was a lisp programmer on lisp machines in the 80's. In terms of productivity, I still have to see a comparable development environment. That said, clojure macro system is powerful enough to have been already abused. Macros help when you have to implement a "compiler" of a new language and you should be able to describe it in a formal notation. Not because is absolutely need by you. It's needed by the users of the new language itself. So, it should be a very useful formal language to be deserved a compiler and a formal notation. If this is not the case, stay away from macros and use pure functional programming style to make your abstractions. You'll feel again the joy of coding sequentially with your analog though, instead of being closer to dumb sequences of bits. And the users of your code will be happier too. I hope clojure macro abuse is not going to be the next accidental complexity. An old lisper and clojure's newbie.
Regarding ordinary macros here are the differences between Lisp's and Clojure's variants:
So, overall, Lisp's approach is more rough, but more flexible. Clojure's macros may be slightly easier to approach, but become harder to use, when you go beyond simple syntax modifications and start to define complete DSLs.
Regarding reader macros, as you know, Clojure doesn't give this option to the user, while CL does. So in CL reader macros find a lot of uses, like string interpolation, internationalization support, SQL DSLs or java interop. Not to mention a plethora of special cases, when reader macros can be used to help create advanced DSLs.
They are both pretty much equivalent in terms of what you can do with them, i.e.:
And now for some differences:
Common Lisp also allows reader macros which allow you to change the behaviour of the reader. This allows you to introduce completely new syntax (e.g. for data structure literals). This might be the reason that your friend describes Clojure's macro system as "weaker" since Clojure does not allow reader macros. In Clojure you are basically stuck with the syntax (macro-name ....)
but apart from that you can do anything you want. Opinion is divided as to whether reader macros a good thing or not: my personal view is not, as it doesn't give you any extra "power" and has the potential to cause extreme confusion.
Clojure has, in my view, a nicer implementation of namespaces that I think make Clojure's macro system easier to use. Every symbol in Clojure is namespace-qualified, so different libraries can define the same symbol different in their own namespace. So +
can be defined separately as clojure.core/+
and my.vector.library/+
without any risk of conflicts. In your own namespace, you can use definitions from another namespace, which will mean that you can choose to take +
from either clojure.core
or my.vector.library
as needed.
Clojure on the other hand has extra literals for maps {}
and vectors []
. These give you a bit more expressivity (in the sense of concise readable syntax) than traditional Lisp s-expressions. In particular, the use of [] for binding forms is a convention in Clojure that I think works well both for macros and normal code - it makes them stand out clearly from the other parentheses.
Clojure is also a Lisp-1 (like Scheme) so it doesn't have a separate namespace for functions and data. Common Lisp is a Lisp-2 which has separate function and data namesapces (so you can have both a function called foo and a data item called foo). I slightly prefer the Lisp-1 approach, since it is simpler and the division between code and data seems a bit arbitrary when you are writing in a functional langauge. This is probably a personal taste thing though.
Overall, the differences are relatively minor. I think Clojure is a bit simpler and more elegant, whereas Common Lisp has some extra features (use at your own risk!). Both are extremely capable, so you can't go wrong choosing either.