This post contains one or more affiliate links. See my Affiliate Policy.
I would broadly and inaccurately categorize materials about learning Clojure as: beginner, cookbook, deep-dive, and applied. Beginner materials will teach you syntax, how to create a project, how to setup an IDE, and take you through some example programs. Good examples of this kind of material would be Living Clojure and Clojure for the Brave and True.
Cookbook materials give you solutions to specific problems. It could be a general cookbook where you look up a problem and get a snippet of code. Some examples of the general cookbook style are Clojure Cookbook and Clojure Recipes. In the cookbook category I would also include books that show you how to work in a particular domain, like Web Development with Clojure and Clojure for Data Science.
Deep-dive materials take one or more features of Clojure and explore them in-depth. This in-depth exploration might include looking at the various functions and parameters, talking about the philosophical underpinnings, discussing the implementation, or even looking at source code. These kind of materials include Core Async Go Macro Internals Part 1 and Part 2, and Joy of Clojure (non-aff).
Finally, applied materials help you understand trade-offs. They usually are based on lessons learned from using Clojure in the field. My ideal applied material would not just solve a problem, but would solve it several different ways, providing guidance about principles that can be extracted. I don’t see many materials with this learning-through-comparison approach. The idea is to learn from experience, and experience is best acquired by doing things over and over in different ways.
Materials in the first two categories tell you what to do. You are meant to emulate them directly. This is appropriate when you are getting started with something new. Deep-dive materials tell you how something works, and I think a richer understanding of a topic is always useful, though it may not help you develop your sense of design. As I imagine them, applied materials help you develop a refined taste for good Clojure design.
I think there is a process to learning. At first you are mostly imitating others, then as you become more familiar with the “vocabulary” and “grammar” of a topic you can begin to form your own “sentences” according to the rules. Eventually, you are able to see past the rules, decide when to apply them, and when to ignore them. First you walk, then crawl, then run and jump. First you follow recipes, then improvise, then write your own recipes. To put one more analogy to it, the beginner and cookbook materials are like giving someone fish, the deep-dive materials are like studying biology and ecology, the applied materials are like learning the art of fishing.
Is there a dearth of materials in the applied category? I think so. I am seeking to provide some applied materials like Clojure Polymorphism, with others forthcoming. However, though there may not be many, there are some applied resources available. In fact, there’s one that has “applied” in its title: Clojure Applied: From Practice to Practitioner (non-aff).
I bought this book when I was surveying for applied material to validate my intuition that there could be more, and maybe I could publish some. I found Clojure Applied to be fantastic, and well written. Here’s an except from Chapter 1, “Model Your Domain”:
Maps and records both use the standard map collection functions for access and modification, but most of the time records are a better choice for domain entities. Records leverage features of the host platform—the Java Virtual Machine (JVM)—to provide better performance in several ways. Records define their type by creating a Java class with a field for each attribute. A record can thus take primitive type hints in its field definition and will create primitive fields in the underlying Java class, which priovides a more efficient representation and faster arithmetic for numbers. The underlying Java class also provides a place to implement Java interfaces and Clojure protocols, placing behavior directly on the record and providing the fastest possible dispatch for those cases.
Given that records give you well-known fields, a type, factory functions, and better performance, they should be your first choice for domain entities. Why might we use maps instead?
One specific case for which you should strongly consider maps is in public-facing APIs, whether they’re expected to be consumed by Java or by Clojure. In an API, it’s important to minimize the constraints on our callers. Requiring them to create instances of our record classes causes some of the details of those classes to be effectively public as well. In this case, maps with a well-known set of keys commit to less and are a simpler and better choice.
This kind of practical, contextual wisdom obviously has its root in using Clojure for many different projects. When people would ask me what is a good book for learning Clojure, I would tell them to pick up one of the beginner books1, and then get Joy of Clojure as a second deeper dive. I believe now that a well supplied Clojure library should have a trilogy of books that includes Clojure Applied.
You may not agree with my categories or with the particular books I’ve put in each category. I’ll be the first to admit that no book falls purely into any one category. However, I hope that this is a useful framework for you to use when thinking about where you are and which materials can help you on your journey to Clojure mastery.
Many years ago the beginning book I recommended was Programming Clojure. I was a technical reviewer for the first edition, but have not read the second edition, though I’m sure it is still excellent. There are so many great introductory books on Clojure, and I’m so far removed from that beginning phase that I hesitate to recommend anything specific. ↩