Clojure Gazette 115
Issue 115February 22, 2015
Macros were one of the things that first drew me to Lisp. The promise of a language that you could extend to suit your problem intrigued me. Like many beginners, I would write small macros to do small tasks for me, so I wouldn't have to write out the code in longhand. Then I would weep when I had to go back to macroless languages.
My understanding of macros has evolved to where I actually rarely use macros. I use functional constructs and data-driven constructs much more. I just wasn't so aware of them before. But even though I don't use macros as much, they are still hugely powerful and important.
Macros are what enable core.async to be a library and not a core part of the language. They let David Nolen experiment with core.match . In short, it enables a kind of linguistic democracy. Clojure is a relatively small language, itself written largely of macros. And that same macro material is available to us as programmers.
I always liked this (fictional?) history of the origin of macros.
The Brave Clojure chapter on macros is a pretty good introduction to macros in Clojure.
Scheme has what are known as Hygienic Macros, which is an attempt to forever rid programmers of the dangers of variable capture. As a macro writer, you're transforming other people's code. You can accidentally rebind a local that that other person was trying to use. Or you could try to use a local that the code you're transforming has rebound. Scheme has a system called Syntax Rules to eliminate this problem.
Clojure takes a different approach which was kind of controversial when it happened. All of the discussion around macros at the time revolved around how to make them safer and safer, to the point of being provably safe. Clojure's approach to macro safety was similar to its safety approach in other areas: make it easy to do the right thing, even though you still allow the wrong thing.
Would you believe that Haskell has macros? It's called Template Haskell. The homoiconic nature of Lisp is touted a lot, but Haskell is also homoiconic in the sense that the AST is available as a Haskell data structure. The AST is just data and can be manipulated in Haskell. If you write a function that takes an AST and returns a new AST, and hook that into the compiler, you've got yourself a macro. Here's a nice tutorial.
Back before Paul Graham was a startup messiah, he was spreading the Lisp gospel. This book could be the single best book on the practical uses of Lisp macros. It's available free for download. I remember studying these macros, especially the more mind blowing ones, to really get what was going on. Be sure to check out the continuation macros.
Now, I usually don't link to things I haven't read. But this book comes up so often I thought it would be neglectful not to link to it. Now with that warning, I'll add another: this is one of those books that is a labor of love. It takes an unconventional view of macros ("safety is for beginners") and takes that view very far. I have had this book on my long reading list for a while, but now that I'm reminded of it, I'm putting it on my short list. Oh, and lots of it is free online.
I'm currently reading this book (about halfway through, though I've skimmed sections from the second half). The first half is basic macro tutorial, but from a Clojure perspective. Although a lot of it I already knew, I did learn several things about Clojure macros that I didn't know before. The rest of the book looks to get more nitty gritty with practical macros you'd actually want to use. I say "use" and not write because a lot of the macros it talks about are simply macros from other libraries. I was disappointed that the delimited continuation chapter does not explain how to write one, as with some of the other macros. For instance, it teaches you how to use criterium, which has a macro for testing the performance of your code. The theme of the book seems to be more "look how the language can be extended without even changing the language", not "people are doing macro wizardry, and here's how you can too". I expect the latter from a macro book, so I would recommend _On Lisp_before this, even if you are into Clojure more than Common Lisp.
Clojure: Deep Walking Macros Youtube
This is a great introduction on how to do some of the more code-transforming macros in Clojure, from Tim Baldridge, who wrote the core.async go macro.