this blog post claims that haskell obsoletes lisp macros, b/c you only need macros to avoid evaluating arguments, which haskell does by default (laziness):
" Macros
Another beauty of Lisp is its macro facility. I’ve not seen its like in any other language. Because the forms of code and data are equivalent, Lisps macro are not just text substitution, they allow you to modify code structure at compile-time. It’s like having a compiler construction kit as part of the core language, using types and routines identical to what you use in the runtime environment. Compare this to a language like C++, where, despite the power of its template meta-language, it employs such a radically different set of tools from the core language that even seasoned C++ programmers often have little hope of understanding it.
But why is all this necessary? Why do I need to be able to perform compile-time substitutions with a macro, when I can do the same things at runtime with a function? It comes down to evaluation: Before a function is called in Lisp, each of its arguments must be evaluated to yield a concrete value. In fact, it requires that they be evaluated in order1 before the function is ever called.
Say I wanted to write a function called doif, which evaluates its second argument only if the first argument evaluates to true. In Lisp this requires a macro, because an ordinary function call would evaluate that argument in either case:
(defun doif (x y) (if x y)) ; WRONG: both x and y have been evaluated already (defmacro doif (x y) `(if ,x ,y)) ; Right: y is only evaluated if x is true
What about Haskell? Does it have a super-cool macro system too? It turns out it doesn’t need to. In fact, much of the coolness of Haskell is that you get so many things for free, as a result of its design. The lack of needing macros is one of those:
doif x y = if x then (Just y) else Nothing
Because Haskell never evaluates anything unless you use it, there’s no need to distinguish between macros and functions. " -- http://newartisans.com/2009/03/hello-haskell-goodbye-lisp/
is it true that that's all that macros are for? it squares with this:
" 3. Purpose: To control evaluation of the arguments.
Since macros are so much harder to use than functions, a good rule of thumb is: don't use defmacro if defun will work fine. So, for example, there would be no reason to try to use a macro for Square: a function would be much easier to write and test. In Lisp, unlike in C, there is no need to use macros to avoid the very small runtime overhead of a function call: there is a separate method for that (the "inline" proclamation) that lets you do this without switching to a different syntax. What macros can do that functions cannot is to control when the arguments get evaluated. Functions evaluate all of their arguments before entering the body of the function. Macros don't evaluate any of their arguments at preprocessor time unless you tell it to, so it can expand into code that might not evaluate all of the arguments. For example, suppose that cond was in the language, but if wasn't, and you wanted to write a version of if using cond. " -- http://www.apl.jhu.edu/~hall/Lisp-Notes/Macros.html
from the comments of http://newartisans.com/2009/03/hello-haskell-goodbye-lisp/ :
harsha says: March 14, 2009 at 2:18 pm
Well, i like lisp(scheme) & haskell too. But note that the need for macros is only eliminated in some cases. In particular, typeclasses like monads & arrows have special notation which helps a lot in using them. If i am not wrong, i think there is no way for you to directly define something for your own custom typeclass, what the do notation does for monads. So you still need macros, either via something like Template Haskell or Liskell.
Sam says: March 14, 2009 at 5:13 pm
I don’t think you really did CL-style macros justice. They can be used for a lot more than just changing the order that arguments are evaluated in — you can create whole new syntactic constructs at will.
For one thing, this means that CL doesn’t tend to ‘lag behind’ in terms of language design, since if another language ever introduces something innovative then you can easily ‘extend lisp’ with macros to add that functionality. There is no need to wait for an updated compiler.
The other thing is that it allows you to build languages tailored to solving the particular problem at hand. DSLs are cool :-)
Having said that, I have issues with lisps that macros just don’t make up for, and love Haskell more in any case :-p Reply John Wiegley says: March 14, 2009 at 6:13 pm
You’re indeed right, I couldn’t do CL justice in this regard. When I referred to being like a “compiler construction set”, I meant to imply a whole world of goodness. Being able to utilize the entire Lisp runtime at compile-time is something that just can’t be expressed in a few words like this. Reply Peter Seibel says: March 14, 2009 at 6:14 pm
I think you do a bit of a disservice to Lisp’s macros: the more interesting macros are not ones that simply delay evaluation of certain forms. More interesting is when a macro transforms something that doesn’t have any meaning into something that does. I give some examples of such macros in Practical Common Lisp (http://www.gigamonkeys.com/book/), in particular Chapter 24 on parsing binary files. Which is not to say that Haskell isn’t cool too. ;-) Reply John Wiegley says: March 14, 2009 at 6:40 pm
You’re so right about that, Peter. Lisp’s macros can be used to transform arbitrary syntax at compile-time into something legal, which allows for extreme freedoms of expression. You can even implement whole DSLs by macro alone — which is just what `LOOP` does, for instance.
So I take back my assertion that it’s essential purpose is to control evaluation, it’s truly a thing of beauty that other languages should take note of. Reply Sam says: March 14, 2009 at 7:22 pm
I would think that many other languages *have* taken note — the issue is that macros only really work in lisp because of the list based syntax. You can certainly do them in a languages with more ‘normal’ syntax (see Dylan and Nemerle, for example) but they’re far less pleasant to use.
There really isn’t a lot you can do about it, either, since it’s the trivial syntax of CL that makes CL macros so easy to use. I think we’ll eventually see reasonable macro systems for complex syntaxes, but AFAIK they haven’t arrived yet.
So, someone might say, why have complex grammars at all? They obviously aren’t *necessary*, since simple ones like those found in lisps are obviously usable, but by providing special syntax for common operations you can make the language more succinct and expressive. One of CL’s failings, in my opinion, is that although the syntax can more or less be adapted to work with anything, it’s still general and never gives you the optimal solution for anything. More specific syntaxes are less flexible, but usually far more expressive and succinct in their particular problem domain.
One day I hope to see a language which allows for specialised syntax, but still translates in into a clean AST which can be manipulated by macros at eval time. Maybe I should make a demo language… :-p
Daniel Weinreb says: March 15, 2009 at 8:21 pm
I’ve been using Lisp for 33 years, since I wrote system software for the Lisp Machine at MIT, and later as a co-founder of Symbolics. I’m using Common Lisp again now, as part of a big team writing a high-performance, highly-available, commercial airline reservation system, at ITA Software. Recently, I started learning Haskell. It’s fascinating and extremely impressive. It’s so different from the Lisp family that it’s extremely hard to see how they could converge. However, you can make a Lisp that is mostly-functional and gets many of the parallelism advantages you discuss. We now have one that I think is extremely promising, namely Rich Hickey’s Clojure.
If you want to program in Common Lisp, read Practical Common Lisp by Peter Seibel, without question the best book on learning Common Lisp ever written. For Haskell, I’ve been reading Real World Haskell by Bryan O’Sullivan?