Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Macros, clojure vs common lisp

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 of Clojure.

When I proposed this one of them said that the macro system is 'weaker'. I wanted to know if this is true, and in what areas.

like image 552
Ferdy Avatar asked Mar 08 '12 01:03

Ferdy


People also ask

When should I use Clojure macros?

Clojure has a programmatic macro system which allows the compiler to be extended by user code. Macros can be used to define syntactic constructs which would require primitives or built-in support in other languages. Many core constructs of Clojure are not, in fact, primitives, but are normal macros.

Is clojure better than Common Lisp?

Clojure is really your better bet. It is highly practical with a good community and excellent Java interop. You never have to worry about finding a good library. The syntax is also a bit more easily parsable than CL.

What are Lisp macros good for?

The Common Lisp macro facility allows the user to define arbitrary functions that convert certain Lisp forms into different forms before evaluating or compiling them. This is done at the expression level, not at the character-string level as in most other languages.

What is the difference between Clojure and Lisp?

Clojure is a dialect of Lisp, and shares with Lisp the code-as-data philosophy and a powerful macro system. On the other hand, Common Lisp is detailed as "The modern, multi-paradigm, high-performance, compiled, ANSI-standardized descendant of the long-running family of Lisp programming languages".


2 Answers

They are both pretty much equivalent in terms of what you can do with them, i.e.:

  • They execute at compile time
  • They can perform arbitrary transformation and generation of code (exploiting the homoiconicity of Lisp code)
  • They are suitable for "extending the language" with new language constructs or DSLs
  • You feel very powerful, and can be very productive (in the beating the averages way)

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.

like image 184
mikera Avatar answered Oct 14 '22 07:10

mikera


Regarding ordinary macros here are the differences between Lisp's and Clojure's variants:

  1. Clojure is Lisp-1, while CL is Lisp-2. The history has shown, that macros in one-namespace language are generally more error-prone, because there's a bigger name collision chance. To mitigate this problem Clojure uses a non-traditional quasi-quote implementation.
  2. But it comes at a cost: as in Clojure symbols inside backquote are eagerly resolved in the namespace, where macros are defined, there are a lot of subtle issues, like this one.
  3. Clojure macros use auto-gensyms. This is advertised as an advantage, and it indeed removes some boilerplate (surely, you can achieve the same in Lisp - see defmacro!). And the conceptual question of when to use gensyms, obviously, remains.

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.

like image 24
Vsevolod Dyomkin Avatar answered Oct 14 '22 07:10

Vsevolod Dyomkin