Clojure for Domain-specific Languages by Ryan D. Kelker
Publisher: Packt Publishing
One of the core strengths of any Lisp, Clojure included, is their support for domain-specific languages (DSL). Writing a DSL in Clojure is a natural and low ceremony design technique. Perhaps that's the reason why the existing literature has been sparse on the subject; there's not really anything special about the mechanisms behind a Clojure DSL. But even if the mechanisms are straightforward, other design decisions are more challenging. An embedded DSL always imply a trade-off. For example, when things go wrong we want to report errors in the language of the domain yet include enough information for the client to react on. A DSL is also challenging from both a syntactic and semantic perspective. A book covering those aspects with balanced discussions on trade-offs would be a welcome addition to my Clojure bookshelf. Unfortunately this book falls short on meeting my expectations, both from a technical perspective and from its content.
The book gets off to a pretty decent start. The author has a fluent style well suitable for technical writing. The first chapter introduces DSL in general, goes into the obligatory discussion on external vs. internal DSL and explains why Clojure is such a good target language. It's nothing groundbreaking, but a simple and straightforward discussion. The author also presents some examples on Clojure DSL. These examples include HTML generation, the audio domain as represented by Music-as-data and finally some image processing with Quil which is cool to a Processing fan such as me. So far so good.
The examples are kept short but they do introduce non-trivial Clojure concepts. Had the rest of the book followed this path by expanding upon the initial material it would have made an interesting read. Instead the author chooses to detour into a basic Clojure introduction. The following chapters introduces functions, basic data structures, Clojure's concurrency support, Java interoperability, etc. None of these topics is even vaguely related to domain-specific languages throughout the text. Sure, the features are all basic building blocks, but we already have multiple books that do a better job at introducing Clojure.
Finally, in the last part of the book, the author returns to the actual subject by presenting a Twitter DSL. The idea is to develop a simple retweet bot which includes basic account management and configuration. I like the fact that it's a real-world example, but the implementation just isn't good enough to serve as a DSL example. The author misses an excellent opportunity to actually discuss how to encapsulate all mutability and side-effects while maintaing a pure functional core of Clojure code. Instead the DSL stands as a thin wrapper around the Java API which means we have side effects everywhere. The author also has a preference for dynamic variables and overuses the construct. But a worse problem is that the functions and macros are too complex. In an introductory book this is simply unacceptable.
I really wanted to like this book but had to give up on it. In its current format I cannot recommend it to anyone. It's a shame since I like the writing style of the author and he takes on an interesting topic. I'd definitely recommend the author to focus on one target audience in future work. A coverage of domain-specific languages will attract intermediate and advanced programmers but these readers will be disappointed with the majority of the material being an introduction to Clojure. Newcomers to the language are better served by other books and will probably not gain enough skills to grasp the DSL parts. The Clojure bookshelf still awaits its first book on domain-specific languages.
Reviewed April 2014