Update: For some reason WP disabled comments when I first posted this. Fixed now.
There’s a thread on c.l.l going, in which people try to find a reason macros haven’t caught on for the past 30 years, despite their immense usefulness. One of the cited arguments was this statement by one of the men in charge of Java process:
The advantages of Java is that it easily serves as a lingua franca - everyone can read a Java program and understand what is going on. User defined macros destroy that property. Every installation or project can (and will) define its own set of macros, that make their programs unreadable for everyone else. Programming languages are cultural artifacts, and their success (i.e., widespread adoption) is critically dependent on cultural factors as well as technical ones.
My claim is that this is about as true as C++’s approach to performance, in which people copy things all the time, because that’s what manual memory management makes them do. Just consider the “design patterns” omnipresent in Java. What is a macro, if not a structured transformation of source, following certain pattern? Of course, I’m saying nothing new here, but I just stumbled upon a particularly good demonstration of why “macros decrease legibility of code” is utter nonsense. Consider this snippet:
(restart-bind
((retry
(lambda () (throw 'retry nil))
:report-function
(lambda (stream)
(write "Retry reading the record." :stream stream))))
(catch 'ok
(loop do
(catch 'retry
(throw 'ok
(unless (read-record)
(error "Record not available.")))))))
Just try analysing it, how fast can you find out what exactly it does? Aren’t braided catch/throws fun? Now consider the same snippet using a macro:
(with-retry (:report "Retry reading the record.")
(unless (read-record)
(error "Record not available.")))
Not only is the code 4x shorter and uses idiomatic naming conventions and code structure, the macro also comes with a docstring and parameters to let you easily influence the working. And most importantly, you only have to understand it once. Whereas in Java every time you encounter a similar-looking snippet, you have to analyse it to see if it’s actually the same thing, or subtly different.
So, to sum up with a checklist, the macroless code is:
- More verbose
- Really complex and confusing
- Hard to spot and identify reliably
- Not documented
- Must be re-invented each time you need it
- Does not ultimately prevent convoluted code from coming up. If your code needs retry functionality, then so it does, and no amount of “ours is a simple language for the masses” can change it. Though if you make it sufficiently painful, people will probably find ways to dillute the apparent complexity amongst modules, only compounding the problems, and/or pretend they don’t really need their program correct, because it’s such a massive PITA to do it.
Now, to be fair, this is not to say that macros can’t be hard — very often they are, because you generally use macros to solve problems that would be even harder without them. You don’t deny surgeons access to endoscopy because they might not be skillfull enough to handle it — instead you make sure they are or have to find another trade. There’s no reason to treat programmers differently.
Saying “macros make code unreadable” is like saying “race bets can only be done on manure-covered floor, or else you won’t know you’re dealing with horses”.

Rob Myers | 14-Jan-08 at 8:23 pm | Permalink
“Every installation or project can (and will) define its own set of macros, that make their programs unreadable for everyone else.”
And every ALGOL installation or project can (and will) define its own set of procedures, that (sic) will make their programs readable for everyone else.
If people don’t include those procedures when they show their source code to other people, how will anyone read and understand ALGOL programs?
It’s impossible. We should stick with FORTRAN.
;-)
Yossi Kreinin | 14-Jan-08 at 9:09 pm | Permalink
I think that in general, the question when (user-defined) high-level abstractions are better than inline lower-level stuff is fascinatingly complicated; the only thing that seems obvious to me is that lousy programmers almost always err on the side of “everything inline”, and good ones err on the other side.
It’s pretty clear to me that Lisp macros failed for purely social reasons though, since C++ templates, which are basically a macro facility from hell, have “succeeded”, and for any possible technical problem with a Lisp macro one can come up with, templates have 10 worse problems. I think people like M-expressions, or think that they like M-expressions, and that pretty much sums it up.
I think the “lingua franca” business has some truth to it, and that’s why CLOS became “built-in”, eventually, but I’ll never believe that this issue influences anyone’s language decisions. For example, C++ doesn’t have a built-in list, and uses an awful form of macro instead; Lisp has a built-in list. Few people seem to mind.
P.S. I get PHP errors instead of entry/comment contents. I only knew what I was replying to because RSS seems to work.
Casper Hauser | 14-Jan-08 at 9:35 pm | Permalink
Few people seem to mind? I think everyone hates C++, with very few exceptions. Especially those who overwhelmingly spend their lives writing C++ code. Prevalence and preference do not correlate.
Grant Rettke | 14-Jan-08 at 10:05 pm | Permalink
I’ve found that people have no trouble writing unreadable code in plenty of languages that haven’t got macros! :)
mathrick | 14-Jan-08 at 10:16 pm | Permalink
@Rob: exactly. Somehow no-one disagrees on the usefulness of functions, but when it comes to macros, which are just a natural application of the same principle to another class of common problems, it’s suddenly taboo.
@Yossi: sorry about PHP troubles, WP is crap, but I only have PHP on this host :(. As to your comment, it’s related to the surgeons things — I just don’t understand how suggesting that we cater for the worst doctors (perhaps without proper education) around would be rightly taken as crazy talk, yet in programming it’s somehow important that you write tools for the dumbest. Perhaps the failure of Lisp to gain popularity (measured in C++, Java and other mainstream languages’ terms) is no failure, but actually a sign of success. You don’t see cranial surgery becoming a fad either.
As a sidenote, there seems to be discussion on reddit about this post, at http://programming.reddit.com/info/65gco/comments
Art | 14-Jan-08 at 11:03 pm | Permalink
Aren’t complied languages just assembly language macros at some level?
Yossi Kreinin | 14-Jan-08 at 11:12 pm | Permalink
I voted it up on reddit, but I couldn’t make myself shove a comment between yours and one by a guy called “death”. “Death”, dammit!
As to “problems with abstraction”: C /does/ have a problem of making it hard to debug in interlaced assembly mode, and making it hard to implement a compiler that makes such debugging tolerable (forget about “easy”) for optimized code. And don’t get me started about C++ and its templates. I’ve had lots of crap for lunch because of that on this very day…
But there are tons of such locally valid remarks on the subject. I still don’t see what they converge to, globally, if you consider the “pros and cons of abstraction” issue. I know wish I had good macros…
Justin Wick | 14-Jan-08 at 11:42 pm | Permalink
I agree with your argument that macros can make code significantly easier to read. Indeed, I often miss that facility when I program in Java. There’s no doubt in my mind that many common design patterns should be given their own language-level syntax extensions and implementation, which would be largely unnecessary in the presence of powerful macros.
However, to paraphrase a great writer, “Hell is other people’s macros.” True, bad coders will always write bad code, but the ability to overload operators and arbitrarily extend language syntax at will… it’s more than most programmers will handle gracefully. Add to that the fact that two individuals may choose the same naming convention and syntax to perform the same task (say, a chain of command), but may have subtly different
While I take solace in the fact that most code is code I will never have to read, if I do have to read crappy code, I would prefer those coders had just a bit less rope…
Matthew | 14-Jan-08 at 11:56 pm | Permalink
Agree partially.
There are other issues with macros, though. They’re hard to support effectively in debugging tools, for one.
I feel lazy evaluation is a superior substitute for many common uses of macros.
mathrick | 15-Jan-08 at 12:15 am | Permalink
@Justin: there are different kinds of rope, and in general, the rope that might be applied to difficult problems will fall into one of two categories: the one that will always hang you and your loved ones, and the one that’s merely extremely dangerous to use. C++ templates are the former, macros are the latter. After all, if there were easy and safe solutions to hard problems, they wouldn’t be hard…
If I had to sum up the post in one sentence, it’d be “Dismissing macros as too difficult is dumb, because you’re confusing the complexity inherent in the problem with the complexity introduced by your solution”.
@Matthew: definitely agreed. I never meant to say that macros were the only hammer you have, only that not having it (or some other, equivalent tool) is stupid. The first rule of writing macros is *not* to use macros unless absolutely necessary, and I stand by that firmly.
Bobby The Programmer | 15-Jan-08 at 12:51 am | Permalink
I read this on Artima, and didn’t quite believe it myself.
Even C/C++ macros can do a lot if properly used, despite lacking the power of Lisp macros. Case in point, the assert() macro.
ken | 15-Jan-08 at 1:06 am | Permalink
The “everyone can read a Java program and understand what is going on” is trivially bogus. I was a Java programmer for years, up through Java 1.4. Each new version of Java has a different syntax, so I have no idea how to read even much Java 1.5 code (generics, metadata, autoboxing, enumerations?). With Lisp, the syntax is consistent, and I just have to read the documentation for whatever macro is used; with Java, the syntax itself changes every couple years.
If even its own native speakers can’t communicate with it, it can’t even qualify for “lingua franca” status. The lingua franca that Sun created is actually the JVM, because it’s used by Jython, JRuby, Rhino, and others.
Web 2.0 Announcer | 15-Jan-08 at 12:42 pm | Permalink
Mathrick no PATANKO PRESS! :: I am not able to rightly comprehend the kind of confusion of ideas that could provoke such a claim…
[…][…]…
Daniel Janus | 15-Jan-08 at 1:58 pm | Permalink
Actually, there is one more way this sort of claim can be dismissed: When one stumbles upon an application of a Lisp macro he is not familiar with, seeing what is really going on is just as easy as macroexpand-1′ing it (or better yet, hitting C-c RET in slime).
Galo | 15-Jan-08 at 6:27 pm | Permalink
I find it very, very hard to believe those people who actually defend Java really believe in themselves. Lingua franca? Java is as much lingua franca as chinese: a lot of people understand it, but still doesn’t mean ANYONE can understand it.
And I am sorry if I offended the chinese language (such a beautiful language) by comparing it with the worst invention in programming languages, EVER.
ken | 15-Jan-08 at 11:31 pm | Permalink
“Java is as much lingua franca as chinese”.
Galo, sorry, I must disagree. Chinese *is* a lingua franca.
Lingua franca does not mean “anyone can understand it”, which is trivially false of all languages. It means “widely used beyond the population of its native speakers”, which Chinese definitely is.
trimtab | 16-Jan-08 at 4:31 pm | Permalink
@ken: Chinese is a “Lingua Franca”? Chinese is “widely used beyond the population of its native speakers”? First, which Chinese are you referring to? (There are 11 native languages (and many more dialects) spoken in China). I would have thought that English (1.2 billion speakers, native + non-native) was more so than Chinese (0.9 billion speakers, mostly native).
ken | 16-Jan-08 at 11:16 pm | Permalink
trimtab: Standard Mandarin, which “serves the function of providing a common spoken language between speakers of different and mutually unintelligible Chinese spoken languages - not to mention between the Han Chinese and other ethnic groups in China”.
– http://en.wikipedia.org/wiki/Lingua_franca#Chinese
Sure, English is also a lingua franca. Nothing about its definition says there can be only one. It’s an attribute of a language, not a contest between them.