If you give someone Fortran, he has Fortran. If you give someone Lisp, he has any language he pleases đ
~ Guy Steele, as quoted in Michael Fogusâ and Chris Houserâs The Joy of ClojureÂ
Are We There Yet? đŠ
~ Rich Hickey (creator of Clojure), title of keynote at JVM Languages Summit (2009).Â
Every now and then a manâs mind is stretched by a new idea or sensation, and never shrinks back to its former dimensions đč
~ Oliver Wendell Holmes Sr., Autocrat of the Breakfast TableÂ
Lisp is worth learning for the profound enlightenment experience you will have when you finally get it; that experience will make you a better programmer for the rest of your days, even if you never actually use Lisp itself a lot đ
~ Eric Raymond, author of The Art of Unix Programming, The Cathedral and the BazaarÂ
Lisp has⊠assisted a number of our most gifted fellow humans in thinking previously impossible thoughts âč
~ Edsger Dijkstra, CACM, 15:10
Scala enthusiasts should note that (1) this post is a direct analog of a recent post that has corresponding thoughts on the finest Scala books, and (2) this post on the best Clojure (think Lisp) books is also highly relevant to you. Allow me to elaborate very briefly: The programmer who has done justice to the notion expressed in the second of the two preceding pointsâin underscoring the eminent relevance of Lisp to Scalaâis David Pollak. In his fine book entitled Beginning Scala (Apress), Pollak observes that
After more than two years of writing and loving Scala, the only regrets that I have are that I didnât learn Lisp in college or take any programming language theory courses in grad school. Each morning that I sit down at the keyboard and start coding Scala, I get a feeling of calm, peace, and power. I know that Iâm going to have another day of taking the ideas in my head and reducing them to a running computer program that will be fast and low in defects.
With that, letâs foray into the land of ClojureâŠ
And what a joy Rich Hickey has given to us programmers by creating Clojureâa functional programming language that runs on the Java Virtual Machine (JVM). It is a Lisp dialect and, as such, an inheritor of limitless expressive power. Though I canât claim to have advanced to the stage of a Lisp hacker, Iâve done plenty of dabbling in Clojure. In this post, Iâll try to distill the essence of the finest resources in print that have helped me grok Clojure. Iâll take an opinionated look at the following books, in turn
- The Joy of Clojure
, Second edition (Manning), by Michael Fogus and Chris Houser đ - Clojure Programming
 (OâReilly) by Chas Emerick, Brian Carper, and Christophe Grand đ - Functional Programming Patterns in Scala and Clojure
 (The Pragmatic Bookshelf) by Michael Bevilacqua-Linn đł - Practical Common Lisp
 (Apress) by Peter Seibel đ - Mastering Clojure Macros
 (The Pragmatic Bookshelf), by Colin Jones đ - On Lisp: Advanced Techniques for Common Lisp
 (Prentice Hall), by Paul Graham đ - Hackers & Painters: Big Ideas from the Computer Age
 (OâReilly), by Paul Graham â±
On our way to my opinionated look at the preceding books, letâs first meander through a preamble, which I hope will also be valuable for youâfeel free to initially jump ahead to the reviews themselves, and return to this preamble afterwards!
But first, in the spirit of obviating redundancyâto avoid referring to the individual Lisp dialects out there as being this dialect or thatâwe will call each of them, simply, a Lisp. Now, of all the languages that run on the JVM, this Lisp is probably the most hard-core, functional programming language in existence, right up there with the likes of Common Lisp and Haskell. While Clojure is not a pure functional programming (FP) language like Haskell, it nonetheless isâunlike Scala, Groovy, JRubyâquite the radical departure from the programming model that most programmers are used to. Allow me to elaborate a bitâŠ
Letâs take Scala which, by the way, is an awesome language in its own right. Scala, though it clearly offers to developers the functional paradigm as part of its programming model, is a hybrid functional object-oriented language, and provides a bridge from object-orientation to FP. Thus, programmers can gradually embrace the functional aspects while operating within the familiar territory of object-oriented (OO) programming.
Enter Clojure, a language that does not provide the familiar OO model within whose comfortable confines most developers have been programming for yearsâto be sure, Clojure, being a Lisp, has plenty of arsenal to help you assemble any and all OO firepower imaginable, albeit in a different style than that which we associate with, say, the OO programming done in Java, or C# for that matter. Consider how Common Lisp, which isâalong with Scheme and Clojureâone of the major Lisps that continues to flourish today, offers the highly sophisticated Common Lisp Object System (CLOS), whose wisdom has indisputably been captured peerlessly by Sonya Keene in her book Object-Oriented Programming in Common Lisp
Coming back to Clojure, you have in this stunningly powerful language an almost bewildering variety of abstraction tools; naturally, this initially places extraordinary demands on a programmer venturing into this language for the first time. A bit like jumping into the deep-end of the swimming pool, getting started with Clojure can be a bit overwhelming.
But rest assured that all your efforts to tame the steep learning curve, which undeniably lies along the road to mastering the abstractions offered by Clojure, will be rewarded through a deepened understanding of the programming craft itself. Even if you donât end up doing your daily programming in this fine language, simply having access to its unparalleled strengthsâand I havenât even mentioned the mind-expanding epiphany one has on first grokking Clojure macrosâcan be a source of inspiration. A short take on that is coming up next.
Clojure, being a Lisp, is the ultimate programming languageâin the spirit of full disclosure, having made the preceding bold statement, I searched online to confirm the definition of a smart aleck, which Merriam Webster defines as âan obnoxiously conceited and self-assertive person with pretensions to smartness or clevernessâ, LOL đ
Itâs difficult to convey the essence of a programming language in one sentence, but John Foderaro has come close: âLisp is a programmable programming languageâ.
Allow me to wedge in here the meme that, in Clojureâsince it happens to be a Lispâthe experience of meta-programming feels far closer to the regular programming that you and I typically do in other languages. But I digress, againâŠ
Importantly for the legions of Java programmers, Clojure is tightly integrated with Java and the JVM, so all your legacy investment in Java codebases remains intact, while allowing seamless (bidirectional) interoperability between Java and Clojure. Like any other Lisp, your code is data in Clojureâsee my comments on homo-iconicity, further along in this post. So programmers can wedge behavior in between reading and evaluating the code (macro-expansion). And therein lies the source of the immense power that Clojure programmers can wield to make programs bend to their willâyes, other languages also have macros, but all macros have not been created equal. But I digress, yet againâŠ
OK, that was another digression, times three, to be preciseâand given the proverbial, three strikes and you are outâI will cease and desist further ramblings đ
So letâs get right on with a rundown of the finest printed resources that Iâm aware of, and which have helped me grok Clojure during the dabbling that Iâve done over the past several years.
1. The Joy of Clojure, Second edition (Manning), by Michael Fogus and Chris Houser đ
The first spot is reserved for a phenomenal book, the likes of which I havenât seen in a great long while: The Joy of Clojure, Second edition (Manning), by Michael Fogus and Chris Houser. Itâs significance makes me want to draw parallels to the Pulitzer prize-winning book Gödel, Escher, Bach: An Eternal Golden Braid, by Douglas R. Hofstadter. OK, so The Joy of Clojure is not going to win the Pulitzer any time soonâthough there are passages peppered throughout, whose lyrical beauty is bound to grip your imaginationâbut what it has done for popularizing Clojure is right up there with what the illustrious GEB did for spreading the recursion meme đ
In full candor, if youâre new to Clojure, trying to follow the narratives in this book is going to be tough. Period. In fact, the authors unabashedly use the drink-from-the-proverbial-firehose approach, much as Steve Yegge noted in the Foreword to the first edition. But The Joy of Clojure can be a fabulous third or even second Clojure book. The reason for this can be traced to these words by its authors, in the Preface
Specifically, this book is about how to write Clojure code The Clojure Way. Even more specifically, this book is about how experienced, successful Clojure programmers write Clojure code, and how the language itself influences the way they create software.
Itâs hard to do justice to capturing the elegance and clarity with which the authors share their deep understanding of exactly what makes Clojure tick. Trust me, their peeling back the onion layers to reveal the essence of this Lisp is highly entertaining, and anything but boring! Refreshingly free of hand-waving, their narrativesâinterleaved with plenty of succinct, high-quality Clojure code snippetsâsucceed spectacularly at pulling together all the strands of Clojureâs abstractions into a well-knit fabric. The reader can reflect upon their newly garnered enlightenment, and confidently continue to deepen their grasp of The Clojure way.
To give you a flavor for the contents of The Joy of Clojure
1. Foundations:
Chapter 1. Clojure philosophy
Chapter 2. Drinking from the Clojure fire hose
Chapter 3. Dipping your toes in the pool Â
2. Data types:
Chapter 4. On scalars
Chapter 5. Collection types Â
3. Functional programming techniques:
Chapter 6. Being lazy and set in your ways
Chapter 7. Functional programming Â
4. Large-scale design:
Chapter 8. Macros
Chapter 9. Combining data and code
Chapter 10. Mutation and concurrency
Chapter 11. Parallelism Â
5. Host symbiosis:
Chapter 12. Java.next
Chapter 13. Why ClojureScript? Â
6. Tangential considerations:
Chapter 14. Data-oriented programming
Chapter 15. Performance
Chapter 16. Thinking programs
Chapter 17. Clojure changes the way you think
Finally, here is Steve Yegge again, in the Foreword to the first edition of The Joy of Clojure
In some sense, all this was inevitable, I think. Lispâthe notion of writing your code directly in tree formâis an idea thatâs discovered time and again. People have tried all sorts of crazy alternatives, writing code in XML or in opaque binary formats or using cumbersome code generators. But their artificial Byzantine empires always fall into disrepair or crush themselves into collapse, while Lisp, the road that wanders through time, remains simple, elegant, and pure. All we needed to get back on that road was a modern approach, and Rich Hickey has given it to us in Clojure.
Again, I can think of no other Clojure book that has brought as much joy to me as this one has; once youâre reasonably comfortable in finding your way around Clojure code, youâll be ready to start partaking in the joy of Clojure as embodied in the pages of The Joy of Clojure
2. Clojure Programming (OâReilly) by Chas Emerick, Brian Carper, and Christophe Grand đ
This book next up is an ideal first book. It is entitled, simply, Â Clojure Programming
For starters, Clojure Programming is replete with tons of high-quality Clojure code snippets which nicely illustrate the point each that those snippets seek to conveyâI was able to load the snippets into the REPL in my IDE (IntelliJ IDEA Ultimate) and step through the code without any problem. What I especially liked about the snippets was the thoughtful annotations accompanying them.
I hasten to qualify with a caveat my earlier note about this being an introductory bookâwhile it is definitely that, do note that it picks up pace rather quickly, so youâll need to stay alert and closely read (and re-read, as need be) the narratives. Adding that this is no watered-down treatment of Clojure by any stretch of the imagination. If youâre looking for a serious, thought-provoking, first book as a companion and guide to your growing understanding of Clojure, this book is peerless.
So while thereâs not much hand-holding in this thoughtful book, the authors most emphatically do not throw the reader into the deep-end of the swimming pool either! Read along carefullyâand do lots of experimentation at your Clojure REPLâand youâll do just fine. In fact, the authors pointedly remark in the Preface that
Often the best way to learn is to dig straight into the nitty-gritty of how a language is used in the real world. If that sounds appealing, the hope is that you will find that at least a couple of the practicums resonate with what you do on a day-to-day basis, so that you can readily draw parallels between how you solve certain categories of problems in your current language( s) and how they may be solved using Clojure. Youâre going to bump into a lot of potentially foreign concepts and language constructs in those chaptersâwhen you do, use that context within the domain in question as your entry point for understanding those concepts using the relevant instructional material in the first part of the book.
Far be it from me to pontificate, but Iâll go ahead and throw this out there anyway: Learning Clojure programming wonât be a cake-walk. Allow me to clarify⊠Unlike learning the typical programming languageâeach with its own unique syntax and whatnotâClojure really doesnât have any syntax to speak of. Yes, I can hear you muttering under your breath, What is he talking about? Well, the deal is that with Clojure being a Lisp, youâll need to get used to writing your code directly in tree form, think abstract syntax tree-coding.
Hmm⊠That sounds dubious, you may well be thinking at this momentâŠÂ Trust me, coding this way feels mightily unnatural at first đ
This is probably best clarified by referring to what Michael Fogus and Chris Houser have to say on this exact pointâin The Joy of Clojure
Writing code is often a constant struggle against distraction, and every time a language requires you to think about syntax, operator precedence, or inheritance hierarchies, it exacerbates the problem. Clojure tries to stay out of your way by keeping things as simple as possible, not requiring you to go through a compile-and-run cycle to explore an idea, not requiring type declarations, and so on. It also gives you tools to mold the language itself so that the vocabulary and grammar available to you fit as well as possible to your problem domain. Clojure is expressive. It packs a punch, allowing you to perform highly complicated tasks succinctly without sacrificing comprehensibility.
Finally, you may be thinking, Why should I stretch myself by picking up Clojure when Iâve got so much already invested in the Java kingdom? Thatâs an absolutely valid question, and which the authors nicely answer as follows in the Preface to this book, Clojure Programming
There are millions of Java developers in the world, but some fewer number are working in demanding environments solving nontrivial, often domain-specific problems. If this describes you, youâre probably always on the hunt for better tools, techniques, and practices that will boost your productivity and value to your team, organization, and community. In addition, youâre probably at least somewhat frustrated with the constraints of Java compared to other languages, but you continue to find the JVM ecosystem compelling: its process maturity, massive third-party library selection, vendor support, and large skilled workforce is hard to walk away from, no matter how shiny and appealing alternative languages are.
If the preceding description fits you, then Clojure Programming is the book for you.
3. Functional Programming Patterns in Scala and Clojure (The Pragmatic Bookshelf) by Michael Bevilacqua-Linn đł
This next book will be ideal for experienced OO programmers who already understand the basics of Clojure, and who now seek to acquire the functional programming style:Â Functional Programming Patterns in Scala and Clojure
In the Preface, the author convincingly makes the case for using both Clojure and Scala code to illustrate the essence of the functional programming style. Hence, he notes
Both Scala and Clojure run on a Java virtual machine (JVM), so they interoperate well with existing Java libraries and have no issues being dropped into the JVM infrastructure. This makes them ideal to run alongside existing Java codebases. Finally, while both Scala and Clojure have functional features, theyâre quite different from each other. Learning to use both of them exposes us to a very broad range of functional programming paradigms.
Next, an excellent introductory chapterâwhich covers the whole notion of how patterns and functional programming are intertwinedâkicks things off. It includes a superb, annotated glossary of all the patterns discussed in the book. Following that is a chapter containing an interesting, extended example (TinyWeb), which is in part a refresher of the basics of Scala and Clojure. The author then walks the reader through the steps to gradually transform TinyWeb from Java to Scala and Clojure, with notes on how to integrate Java code with Scala and Clojure.
What follow next are the two major sections that make up the remainder of Functional Programming Patterns in Scala and Clojure
By exploring both the similarities and the differences between Scala and Clojure, you should get a good feel for how each language approaches functional programming and how it differs from the traditional imperative style you may be used to.
The second section follows, delving into the details of patterns that are native to the functional paradigm. The rationale for the heavy reliance on immutability, the wisdom in making higher-order functions (HOFs) the primary unit of composition, and creating little languages to solve specific problemsâthink DSLs, which, by the way, Lisp introduced to the worldâare all covered in this section.
For a flavor of this fine bookâs contents, this thoughtful books is organized like so
Table of Contents
Acknowledgments
Preface
How This Book Is Organized
Pattern Template â
Why Scala and Clojure â
How to Read This Book â
Online Resources Â
1. Patterns and Functional Programming
1.1 What Is Functional Programming? â
1.2 Pattern GlossaryÂ
2. TinyWeb: Patterns Working Together
2.1 Introducing TinyWeb â
2.2 TinyWeb in Java â
2.3 TinyWeb in Scala â
2.4 TinyWeb in Clojure  Â
3. Replacing Object-Oriented Patterns
3.1 Introduction â
Pattern 1. Replacing Functional Interface â
Pattern 2. Replacing State-Carrying Functional Interface â
Pattern 3. Replacing Command â
Pattern 4. Replacing Builder for Immutable Object â
Pattern 5. Replacing Iterator â
Pattern 6. Replacing Template Method â
Pattern 7. Replacing Strategy â
Pattern 8. Replacing Null Object â
Pattern 9. Replacing Decorator
Pattern 10. Replacing Visitor â
Pattern 11. Replacing Dependency Injection  Â
4. Functional Patterns â
4.1 Introduction â
Pattern 12. Tail Recursion â
Pattern 13. Mutual Recursion â
Pattern 14. Filter-Map-Reduce â
Pattern 15. Chain of Operations â
Pattern 16. Function Builder â
Pattern 17. Memoization â
Pattern 18. Lazy Sequence â
Pattern 19. Focused Mutability â
Pattern 20. Customized Control Flow â
Pattern 21. Domain-Specific LanguageÂ
5. The EndÂ
Bibliography
Used together, these patterns let programmers solve problems faster and in a more concise, declarative style than with object-oriented programming alone. If youâre using Java and want to see how functional programming can help you work more efficiently, or if youâve started using Scala and Clojure and canât quite wrap your head around functional problem-solving, this is the book for you.
Arenât we lucky to have in Clojure a Lisp that runs on the stellar piece of software engineering that is the JVM? A blessing counted đ
4. Practical Common Lisp (Apress) by Peter Seibel đ
We have on our hands a powerful book in Practical Common Lisp
First, Iâve got a confession to make, since it directly ties in with this book: As much as Iâm passionate about crafting quality software, I care equally about the craft of writing, seeking to serve the reader with unpretentiousness and humor. Stuffiness is out! As one classic Pink Floyd song memorably tells us, just the basic facts. Well, letâs see now⊠So I jettisoned off my copies of The Chicago Manual of Style and Rogetâs International Thesaurus, ages agoâalong with several hundred other books for reasons of expediencyâwhen I pulled up stakes and moved from Minnesota to Texas. Oh, and I donât consult the dictionary much now when I write, plus I believe that all of us should have a good laugh at ourselves every now and then, because stuffiness just isnât for me đ
OK, so hereâs what my preceding admission has to do with Practical Common Lisp: The writing is crisp and engaging, reminding me in several ways of the stellar writing with which Paul Graham has graced his essays and booksâon the subject of Lisp programming, on acquiring the craft of programming, as well as on other diverse subjects. In this book, Peter Seibel regales us with hefty doses of eminently accessible Lisp wisdom, all served in a highly entertaining way. Yes, the Common Lisp language has a decidedly different vision than what we have in The Clojure Way. And then there is Schemeâwhich is the third of the three Lisps that continue to flourishâfollowing yet another (decidedly minimalist) design philosophy that specifies a tiny standard core. But I digressâŠ
The point is that all Lisps share a common heritage, which is cross-cutting across them all. So pretty much everything you learn from this book will help you out with understanding Clojure better.
Yes, while Clojure has introduced pleasant innovationsâseamless interoperability with Java code, a rich set of literals for data and collections like vectors, maps, sets, and listsâit still retains its Lisp roots. It was really while reading and absorbing this wonderful book, Practical Common Lisp
This is an amazingly well-written book that you should not miss, even if you never end up writing even a single line of Common Lisp code.
Oh, and did I mention the delightful observation by the author in his intro that he ââŠis either a writer-turned-programmer or a programmer-turned-writerâ. That really sets the tone for the whole book. Granted, this book wonât be a cake-walk, but then again, itâs Lispâa formidable language that has to be reckoned with on its own termsâthat weâre talking about. And with this power comes the inevitable complexity. But the fantastic news is that all the accompanying complexity is essential in nature, not incidental. Neal Ford has probably articulated this the best; hereâs his take on the tension between, and the dichotomy of, essential-accidental-versus-complexity in his fine book titled The Productive Programmer
Essential complexity is the core of the problem we have to solve, and it consists of the parts of the software that are legitimately difficult problems. Most software problems contain some complexity. Accidental complexity is all the stuff that doesnât necessarily relate directly to the solution, but that we have to deal with anyway.
While the preceding quote from Neal Ford is in the context of the origins of service-oriented architecture (SOA)âan architectural style whose need derives from companies trying to mitigate the amount of accidental complexity that has built up over timeâthe notion of these two types of complexity can easily be generalized to the domain of programming languages. At this moment, you may well be thinking to some languages in which programming was a joy; in other languages, perhaps less so. And I didnât mention FORTRAN, or did I? Oops⊠Then again, letâs try visualizing a book called The Joy of FORTRAN, shall we? đ
So I think we agree that all languages inevitably carry some baggageâitâs the relative degree of the conceptual burden that a programmer has to bear, when using the model of a given language, which sets a language apart from others. To put this in more concrete terms, allow me to share an anecdote based on my half-dozen years of programming in C++. With all due respect to those for whom the experience of programming in C++ is a pleasant and productive oneârather than the harrowing torment of Sisyphus, penitently toiling away at pushing the boulder uphillâgiven the bewildering variety of rules, exceptions-to-said-rules, which is the conceptual burden that a C++ programmer has to bear.
The setting for my half-dozen years of programming in C++ was the beautiful state of Minnesotaâbeautiful, but the harsh, frigid winter season, however, seemed to stretch interminably each yearâso the more I would try to warm up to C++, the more that recalcitrant mule of a stubborn language would dig in its heels, responding with nothing but mirthless frostiness, ouch.
This rueful reminiscing notwithstanding, as a long-time subscriber to the magazine MIT Technology Review, I couldnât help but recall just how strongly I had resonated with what its then editor Jason Pontin had to say on this exact topic in the MIT TR editorial entitled âOn Rulesâ, back in January 1, 2007. Part of what he neatly articulated addresses precisely the same pain-point that I referred to a moment agoâthe burden that some languages place on its practitioners. The editor went on to observe the
âŠgenerations of programmers who have struggled with C++âs quirks of syntax and features overload⊠A useful programming language should be what computer scientists call an abstraction of the underlying complexity of control flows and data structures. C++ preserves for programmers the maximum possible freedom of expression; but as ÂâJLeslieâ (another Slashdot commentator) admitted, âThe cost was that it wasnât much of an abstraction.â
C++ is notoriously hard to learn and use. Partly, this is owing to the difficulty of mastering the languageâs paradigmatic method⊠But mainly it is because software developers are free to express their ideas in C++ in a bewildering variety of forms.
Amen. But letâs move on, shall we, onward and away from talk of purgatorial experiences?
Before we do, I feel compelled to reiterate, so please take note: The preceding impressions are mine alone. I would like to think, and in fact hope, that programming in C++ for some others has been far more pleasant than mine. I wish the C++ communityâfrom which I parted many years agoâevery success, and truly wish them well.
So when you program in Clojureâas you would with any Lispâyou get to define your own domain-specific languages (DSLs) to suit your needs. Thereâs no conceptual burden whatsoever, because you become a language designer, making your own DSLs wherein you encode how your specific business use cases work. Without jumping ahead too much, I point you to a sublime quote from Paul Graham (in my review of his book On Lisp: Advanced Techniques for Common Lisp
Ah, lest I forget, hereâs a brief rundown of the cool stuff which awaits the reader in the pages of Practical Common Lisp
CHAPTER 1 Â Â Introduction: Why Lisp?
CHAPTER 2 Â Â Lather, Rinse, Repeat: A Tour of the REPL
CHAPTER 3 Â Â Practical: A Simple Database
CHAPTER 4 Â Â Syntax and Semantics
CHAPTER 5 Â Â Functions
CHAPTER 6 Â Â Variables
CHAPTER 7 Â Â Macros: Standard Control Constructs
CHAPTER 8 Â Â Macros: Defining Your Own
CHAPTER 9 Â Â Practical: Building a Unit Test Framework
CHAPTER 10 Â Numbers, Characters, and Strings
CHAPTER 11 Â Collections
CHAPTER 12 Â They Called It LISP for a Reason: List Processing
CHAPTER 13 Â Beyond Lists: Other Uses for Cons Cells
CHAPTER 14 Â Files and File I/O
CHAPTER 15 Â Practical: A Portable Pathname Library
CHAPTER 16 Â Object Reorientation: Generic Functions
CHAPTER 17 Â Object Reorientation: Classes
CHAPTER 18 Â A Few FORMAT Recipes
CHAPTER 19 Â Beyond Exception Handling: Conditions and Restarts
CHAPTER 20 Â The Special Operators
CHAPTER 21 Â Programming in the Large: Packages and Symbols
CHAPTER 22 Â LOOP for Black Belts
CHAPTER 23 Â Practical: A Spam Filter
CHAPTER 24 Â Practical: Parsing Binary Files
CHAPTER 25 Â Practical: An ID3 Parser
CHAPTER 26 Â Practical: Web Programming with AllegroServe
CHAPTER 27 Â Practical: An MP3 Database
CHAPTER 28 Â Practical: A Shoutcast Server
CHAPTER 29 Â Practical: An MP3 Browser
CHAPTER 30 Â Practical: An HTML Generation Library, The Interpreter
CHAPTER 31 Â Practical: An HTML Generation Library, the Compiler
CHAPTER 32 Â Conclusion: Whatâs Next?
Index
For those venturing into Clojure land for the first time, this book will be an excellent companion to Clojure Programming
5. Mastering Clojure Macros (The Pragmatic Bookshelf), by Colin Jones đ
I found a gem of a book in this title:Â Mastering Clojure Macros
While this book may well be petite and slender
Trust me, itâs in every way a true mind-bender
Hmm⊠Coming on the heels of the prior review, youâre likely forming the impression of Clojure being a language unlike any other that youâve encounteredâassuming that youâre a newcomer to the Lisp paradigm. In this regard, the following comments about this book, Mastering Clojure Macros, by legendary programmer, Robert âUncle Bobâ Martin will hopefully help clarify
So you thought you knew Clojure? This book changes everything. From its deceptively simple beginnings, to its very challenging conclusion, these pages will help you master the highest power tools of this already powerful language.
Much as its title heralds, this book is all about macros, up close and personal đ
As a side-note, and if you want to stash away a data point on the topic of macros⊠When you really, really want to knock yourself out on macrosâonce youâve got enough understanding of Clojure under your beltâlook into tackling the meta mind-bender of a book entitled Let Over Lambda: 50 years of Lisp
One of the conclusions that we reached was that the âobjectâ need not be a primitive notion in a programming language; one can build objects and their behavior from little more than assignable value cells and good old lambda expressions.Â
Hold on to that thought when you contemplate doing OO programming, and then some, in a Lisp such as ClojureâŠ
OK, getting right back now to Mastering Clojure Macros
Basically, you can do meta-programming with Clojure macros that is simply impossible in other fine languagesâincluding Ruby, C++, and even Scala, though there is an ongoing effort towards bringing compile-time meta-programming to Scala. Much as I love programming in Scala, I matter-of-factly have to confess that Lispsâbecause they are the only homo-iconic languages on this planetâprovide the accruing raw programming power which you, as a Clojure programmer, can wield to bend programs to your will.
Very briefly, to help you assimilate my preceding remark on homo-iconicity, hereâs a remarkably compelling round-up of this concept, as described in the pages of Clojure Programming (OâReilly) by  by Chas Emerick et al, and which I also review in this postâthe authors point out that
The use of parentheses (as a textual representation of lists) is an outgrowth of Clojure being a homo-iconic language. Weâll see what this means in (the side-notes for) Homo-iconicity, but the ramifications of it are manifold: homo-iconicity enables the development and use of meta-programming and domain-specific language constructs simply unavailable in any programming language that is not homo-iconic.
Circling back now to my earlier remark about how the author thoughtfully presents considerable explanations in Mastering Clojure Macros
Macros in Clojure are an elegant meta-programming system, a means to accomplish goals that might seem impossible in other languages. How hard would it be to add pattern matching or a new control flow structure to your language as a library (rather than patching the core language)? In Clojure, people like you and me have the power to do these things ourselves.
And a bit more nuts-and-bolts pointâsuper helpful, of courseâis when the author invites the reader to imagine like so
âŠCan you imagine whyâaside from trivia and aestheticsâwe actually care that the code can be viewed as normal data? The most compelling answer is that it makes it relatively straightforward to manipulate programs. When we do meta-programming in Clojure, we can think at the expression level rather than at the textual level. It may not seem like a big deal right now, but as youâll see over the course of this book, this simple concept is the key that allows you to write macros.
Be prepared to re-read Mastering Clojure Macros many times over; its brevity utterly belies the amount of knowledge thatâs packed in this slender book. Finally, to end this bookâs review, I leave you with an evocative quote, which could well be applied to undertaking the journey to grok Clojure macros
There are subjectsâŠthat can be appreciated only if you make an effort proportional to their innate complexity.  To hearken back to something like the language of courtly love in medieval France, there are certain objects of our affection that reveal their beauty and charm only when we make a chivalrous but determined assault on their defenses; they remain impregnable if we donât lay siege to the fortress of their inherent complexity.Â
~ Christian Queinnec, in Lisp In Small Pieces (Cambridge University Press, 2003), p. xvi
In the end, hereâs a brief rundown of the contents in Mastering Clojure Macros
- Build a Solid Foundation
- Advance Your Macro Techniques
- Use Your Powers Wisely
- Evaluate Code in Context
- Speed Up Your Systems
- Build APIs That Say Just What They Mean
- Bend Control Flow to Your Will
- Implement New Language FeaturesÂ
6. On Lisp: Advanced Techniques for Common Lisp (Prentice Hall), by Paul Graham đ
In my mindâand itâs a coincidence that we were talking about the Pulitzer prize earlierâhere we have a Lisp hacker of the highest order, in the fine tradition of Timothy Hart and Guy Steele, besides being a writer extraordinaire whose writings could easily garner a Pulitzer. But oh well, founding the path-breaking Y Combinator is perhaps a decent-enough consolation prize đ
Weâre of course talking about Paul Graham. Iâve written about Paul Graham and his stellar work in some of my earliest posts that you can find on this blog-site. And itâs his book On Lisp: Advanced Techniques for Common Lisp
With that, letâs dive right into this tour de force đ
But first, allow me to fulfill a promise I had made earlier, while reviewing Peter Seibelâs Practical Common Lisp
So I circled back to a post that I had published much earlierâyou can read it in its entirety in an earlier post, entitled On Paul Grahamâs Essays, and of Y CombinatorâI found the section, including the sublime quote that I wished to cite. Look in this quote, too, for the sublime metaphors that the author uses in the second of the following two paragraphs with the cue sentence Language and program evolve together
âŠThe traditional approach is called top-down design: you say âthe purpose of the program is to do these seven things, so I divide it into seven major subroutines. The first subroutine has to do these four things, so it in turn will have four of its own subroutines,â and so on. This process continues until the whole program has the right level of granularityâeach part large enough to do something substantial, but small enough to be understood as a single unit.Â
Experienced Lisp programmers divide up their programs differently. As well as top-down design, they follow a principle which could be called bottom-up designâchanging the language to suit the problem. In Lisp, you donât just write your program down toward the language, you also build the language up toward your program. As youâre writing a program you may think âI wish Lisp had such-and-such an operator.â So you go and write it. Afterward you realize that using the new operator would simplify the design of another part of the program, and so on. Language and program evolve together (italics are mine). Like the border between two warring states, the boundary between language and program is drawn and redrawn, until eventually it comes to rest along the mountains and rivers, the natural frontiers of your problem. In the end your program will look as if the language had been designed for it. And when language and program fit one another well, you end up with code which is clear, small, and efficient.
On Lisp is a highly literate, engaging, down-to-earth, and precise discussion of all things Lisp macros. With the exception of one other book, Iâm not aware of any other books that cover this topic half as substantially; the other superb book I allude to is entitled Let Over Lambda: 50 years of Lisp
Wrapping up that ever-so-brief segue into an allied gem as I didâHoyteâs book Let Over Lambdaâhereâs an eloquent tribute from that book (to On Lisp), with its authorâs italicization kept intact
On Lisp is one of those books that you either understand or you donât understand. You either adore it or you fear it. Starting with its very title, On Lisp is about creating programming abstractions which are layers on top of lisp. After weâve created these abstractions we are free to create more programming abstractions which are successive layers on earlier abstractions.
And speaking of this book of Lisp loreâthe magnum opus, On Lisp
When someone asked Louis Armstrong what jazz was, he replied âIf you have to ask what jazz is, youâll never know.â But he did answer the question in a way: he showed people what jazz was. Thatâs one way to explain the power of Lispâto demonstrate techniques that would be difficult or impossible in other languages. Most books on programmingâeven books on Lisp programmingâdeal with the kinds of programs you could write in any language. On Lisp deals mostly with the kinds of programs you could only write in Lisp. Extensibility, bottom-up programming, interactive development, source code transformation, embedded languagesâthis is where Lisp shows to advantage.Â
I hoped to do more than simply demonstrate the power of Lisp, though. I also wanted to explain why Lisp is different. This turns out to be a subtle questionâtoo subtle to be answered with phrases like âsymbolic computation.â What I have learned so far, I have tried to explain as clearly as I can.Â
I hope reading this book will be fun. Of all the languages I know, I like Lisp the best, simply because itâs the most beautiful. This book is about Lisp at its lispiest. I had fun writing it, and I hope that comes through in the text.
I donât know about your reaction, but when I giddily read this passages, I sure fell for it, hook, line, and sinkerâIâm a sucker for ravishing prose like that and, of course, for beautiful code.
Again, itâs nearly impossible to convey a sense for the precision and elegance with which Paul Graham dissects, nay vivisects, the various topics he covers in the course of his wide-ranging discussions of all things Lisp macros. But Iâll try some more and paraphrase what Jeremy Ashkenasâcreator of CoffeeScript, Backbone.js, and Underscore.jsâsays about Clojure programmer extraordinaire Michael Fogusâ book entitled Functional JavaScript: Introducing Functional Programming with Underscore.js
This is a terribly exciting book⊠It breaks down⊠Lisp programming into its basic atoms, and builds it back up again into edifices of terrifying cleverness that will leave you wondering. Itâs rare that a programming book can take you by surprise, but this one will.
Again, I paraphrased above the words of Jeremy Ashkenas to reflect my own, near-identical, sentiments toward On Lisp.
Whatâs quite amazing, too, about On Lisp is the exposure to a plethora of Lisp technique youâll get by poring over its pages. In fact, as the author himself notes, âJust as a tour of New York could be a tour of most of the worldâs cultures, a study of Lisp as the programmable programming language draws in most of Lisp techniqueâ.
Speaking of Lisp technique, when youâre ready for exposure to additional mind-expanding technique, albeit with far less focus on Lisp macrosâfor which On Lisp and Let Over Lambda remain the champsâyou simply canât go wrong with perusing the gem from Peter Norvig entitled Artificial Intelligence Programming: Case Studies in Common Lisp
At the moment, while I donât have room to delve into my opinions on the intriguing content of Peter Norvigâs PAIP, Iâll leave you with a couple of points that its author makes about Lisp, the programmable programming language, specifically about Common Lisp
Lispâs flexibility allows it to adapt as programming styles change, but more importantly, Lisp can adapt to your particular programming problem. In other languages you fit your problem to the language; with Lisp you extend the language to fit your problem.Â
Because of its flexibility, Lisp has been successful as a high-level language for rapid prototyping in areas such as AI, graphics, and user interfaces. Lisp has also been the dominant language for exploratory programming, where the problems are so complex that no clear solution is available at the start of the project. Much of AI falls under this heading.
With a blend of rigor and writing virtuosity permeating the pages of On Lisp
Nowâs the time that our dreams are finally coming true
Feels so good, weâre cryingÂ
Nowâs the time when itâs down to me and you
Spread these wings, weâll be flying
1. The Extensible Language
2. Functions
3. Functional Programming
4. Utility Functions
5. Returning Functions
6. Functions as Representation
7. Macros
8. When to Use Macros
9. Variable Capture
10. Other Macro Pitfalls
11. Classic Macros
12. Generalized Variables
13. Computation at Compile-Time
14. Anaphoric Macros
15. Macros Returning Functions
16. Macro-Defining Macros
17. Read-Macros
18. Destructuring
19. A Query Compiler
20. Continuations
21. Multiple Processes
22. Nondeterminism
23. Parsing with ATNs
24. Prolog
25. Object-Oriented Lisp
There you have it, a radiant gem of a book. And a first-class companion for On Lisp, should you wish to keep a reference handy while you study it, will be the following: So I also have a copy of Paul Grahamâs ANSI Common Lisp
Richard Gabriel once half-jokingly described C as a language for writing Unix. We could likewise describe Lisp as a language for writing Lisp. But this is a different kind of statement⊠It opens up a new way of programming: as well as writing your program in the language, you can improve the language to suit your program. If you want to understand the essence of Lisp programming, this idea is a good place to start.
Enough said. There are a ton of substantial, extremely high-quality programming examples in ANSI Common Lisp
7. Hackers & Painters: Big Ideas from the Computer Age (OâReilly), by Paul Graham â±
Last, but certainly not the least, is this beguiling and highly entertaining book, Hackers & Painters: Big Ideas from the Computer Age
This charming book will be especially helpful to someone completely new to the Lisp family of languages, including Clojure. While there isnât much nuts-and-bolts programming advice at all in this book, thereâs definitely a hefty dose of eminently accessible material thatâll help you appreciate and understand the Lisp philosophy. Two additional resource will also be worthy of your attention, so I mention them in the same breath
- Eric Raymondâs wise post entitled How To Become A HackerÂ
- Peter Norvigâs riotously entertaining and wise take on how to Teach Yourself Programming in Ten Years
The careful reader may have noted that one of the quotes that kicks things off in this post is from Eric Raymondâs helpful post cited above. Letâs now dive right into our final book review. But first letâs disabuse ourselves of any vagueness that might surround the sense in which the overloaded word hacker is used here, both by the authorsâin their respective books, which Iâm reviewing hereâand by myself. Hereâs how Paul Graham introduces this word in the Preface to Hackers & Painters
Hackers? Arenât those the people who break into computers? Among outsiders, thatâs what the word means. But within the computer world, expert programmers refer to themselves as hackers. And since the purpose of this book is to explain how things really are in our world, I decided it was worth the risk to use the words we use.
With that definition to level-set our understanding of exactly who hackers are, I draw your attention to the fact that thereâs so much brilliantly endearing and accurate observationsâincluding those on the role and impact of computing on the larger world, but more on that laterâjam-packed into this book that youâll want to pore over every nook and cranny. And I literally mean, like, right down to the Notes sectionâwhich everyone, including myself, skips when reading a typical bookâbecause Hackers & Painters
To that end, hereâs the authorâs delightful observation on the topic of interruptions, which appearsâsee I told you to avoid skipping anythingâin the Notes section đ
Different kinds of work have different time quanta. Someone proofreading a manuscript could probably be interrupted every fifteen minutes with little loss of productivity. But the time quantum for hacking is very long: it might take an hour just to load a problem into your head. So the cost of having someone from personnel call you about a form you forgot to fill out can be huge. This is why hackers give you such a baleful stare as they turn from their screen to answer your question. Inside their heads a giant house of cards is tottering.
Enough said.
What makes Hackers & Painters truly special is the exceptionally cultivated writing skill that the author wields in sharing insights, which of course are based on his equally exceptional programming skills. To get a sense for this virtuosity on display, in both spheresâthe one where man communicates with fellow readers, the other where man communes with the computerâthereâs no substitute for reading the book itself. My impressions notwithstanding, and which Iâve tried to convey here, you really have to read this book and form your own assessment.
By the way, even as I wrote the second-half of the preceding point aboveâthe sphere wherein man communes with the computer his codified logicâI was acutely aware of the following excellent advice shared by MIT professors Harold Abelson and Gerald Jay Sussman who, along with Julie Sussman, crafted the classic tome, The Structure and Interpretation of Computer Programs
...a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute.
So Iâve read Hackers & Painters
Each time I re-read this delicious book, I seemed to find anew yet another insight, and this circling back continues as a virtuous cycle to this day, illuminating and informing me, deepening my appreciation for the role of computingâespecially his stellar coverage of (Common) Lispâin the digital world whose infrastructure is unerringly gravitating toward embracing the complexity-taming foundational work with which John McCarthy enlightened the functional world in 1958.
Here is Paul Grahamâs sparkling-with-wit take on this very topic
What I mean is that Lisp was first discovered by John McCarthy in 1958, and popular programming languages are only now catching up with the ideas he developed then.Â
Now, how could that be true? Isnât computer technology something that changes very rapidly? In1958, computers were refrigerator-sized behemoths with the processing power of a wristwatch. Â How could any technology that old even be relevant, let alone superior to the latest developments?
Iâll tell you how. Itâs because Lisp was not really designed to be a programming language, at least not in the sense we mean today⊠But in late1958, Steve Russell, one of McCarthyâs grad students, looked at this definition of eval and realized that if he translated it into machine language, the result would be a Lisp interpreter.Â
Suddenly, in a matter of weeks, McCarthy found his theoretical exercise transformed into an actual programming languageâand a more powerful one than he had intended. So the short explanation of why this 1950s language is not obsolete is that it was not technology but math, and math doesnât get stale.
Hackers & Painters
1. Why Nerds Are Unpopular
2. Hackers and Painters
3. What You Canât Say
4. Good Bad Attitude
5. The Other Road Ahead
6. How to Make Wealth
7. Mind the Gap
8. A Plan for Spam
9. Taste for Makers
10. Programming Languages Explained
11. The Hundred-Year Language
12. Beating the Averages
13. Revenge of the Nerds
14. The Dream Language
15. Design and ResearchÂ
Notes
Glossary
When it was first developed, Lisp embodied nine new ideas. Some of these we now take for granted, others are only seen in more advanced languages, and two are still unique to Lisp. The nine ideas are, in order of their adoption by the mainstreamâŠ
- Conditionals.
- A function type.
- Recursion.
- Dynamic typing.
- Garbage-collection.
- Programs composed of expressions.
- A symbol type.
- A notation for code using trees of symbols and constants.
- The whole language there all the time.
Many languages have something called a macro. But Lisp macros are unique. And believe it or not, what they do is related to the parentheses. The designers of Lisp didnât put all those parentheses in the language just to be differentâŠÂ
âŠYou write programs in the parse trees that get generated within the compiler when other languages are parsed. But these parse trees are fully accessible to your programs. You can write programs that manipulate them. In Lisp, these programs are called macros. They are programs that write programs.Â
Programs that write programs? When would you ever want to do that? Not very often, if you think in Cobol. All the time, if you think in Lisp.
So there, Iâve done my level best to give you a flavor of this marvelous book, Hackers & Painters
Oh, goodness. I wasnât quite planning on this⊠So I dwell in a world powered by the duo dynamos of Java and Scala, along with their respective frameworks each. But my fondness for Clojure in particular, and the Lisp philosophy in general, never really left me, I realize. Functional programming, math, oh my!
In putting together my thoughts for these reviewsâin particular while reviewing the last two books, where I let Paul Graham have the last wordâIâm grippingly reminded, yet again, how some things just never go out of style. Ever.
We keep coming back to the basics. Functional programming is inspiring a renaissance in the way we craft software. MapReduce, Domain-Specific Languages, and Lambda Architecture, anyone?
This point is underscored by Michael Fogus and Chris Houser in their stellar book, The Joy of Clojure
Go to any open source project hosting site, and perform a search for the term Lisp interpreter. Youâll likely get a cyclopean mountain of results from this seemingly innocuous term. The fact of the matter is that the history of computer science is littered with the abandoned husks of Lisp implementations. Well-intentioned Lisps have come and gone and been ridiculed along the way, and yet tomorrow, search results for hobby and academic Lisps will have grown almost without bounds.
And yesâClojure, Common Lisp, Schemeâlong live all the Lisps of the world!
And so we come to the end. Much as I mentioned at the outset, I invite your commentsâHaving now read my brief take each on the preceding half-dozen booksâŠ
- Do you find that your experience of reading any of these books was different than mine?Â
- Perhaps some qualities that I didnât cover are the ones that you found the most helpful as you learned Clojure and its ecosystem.Â
- Did I leave out any of your favorite Clojure book(s)?Â
- If so, what could I also review, perhaps in a future blog post.
- Iâve covered only a partial list of the Clojure books that Iâve read, necessarily limited by the time availableâŠ
My hope is that these brief vignettes will help you in your journey to grokking Clojureâmeandering out of necessity through its close cousin, Common Lispâotherwise, you will miss out on some evergreen classics that inform how Clojure has been put together.
Bon voyage, and I leave you with a photo of a pseudo-random section of one of my bookshelvesâheavens behold, I do confess this section se a tad biased toward Clojure material đ