Trying to Fall In Love With Clojure Again
On returning to a language that refuses to apologise for what it is.
There’s a particular kind of disorientation that comes from returning to something you once knew well. It’s not quite amnesia. It’s more like walking back into a house you used to live in and finding someone’s rearranged all the furniture.
The light still comes through the same windows. But your muscle memory keeps reaching for a light switch that isn’t there anymore.
That’s where I am with Clojure right now.
I spent some real time with it a few years back, REPL driven development, the joy of the parentheses once you stop fighting them, the dawning realisation that immutability isn’t a restriction but a relief.
I loved it.
And then, as happens, life happened. I left the Clojure house I was working with. Other projects, deadlines and languages became more a priority. Clojure drifted to the back of the shelf.
So I came back. Fired up a new project. And immediately felt like a tourist.
The Leiningen Problem (Except It Isn’t Leiningen Anymore)
When I left, Leiningen was just how you did things. lein new, lein run, lein repl. It was friendly and opinionated in the way a good framework should be — confident enough that you didn’t have to be.
Coming back, the community has largely shifted to deps.edn and the Clojure CLI. And look, I understand why. deps.edn is genuinely more composable. It’s just data. It fits the Clojure philosophy better than a tool with its own DSL bolted on the side. I get it.
But intellectually understanding something and feeling it are different things.
This is the tax of returning. You don’t get to start from where you left off. You have to re-earn it.
The REPL still works the same. The language is still the language. But the scaffolding has shifted, and scaffolding matters more than we like to admit. It’s the difference between wanting to write code and wanting to delay writing code by reading documentation about tooling.
The Documentary and the Phrase That Wouldn’t Leave Me Alone
In the middle of all this, I watched the Clojure documentary, A Movie About the Clojure Programming Language and I came away with one phrase rattling around in my head.
“Simplicity is a choice.”
It’s such a Rich Hickey thing to say.
On one level it sounds almost smug, like something you’d embroider on a cushion for a certain kind of programmer’s living room. But reader, sit with it for a moment.
Hickey’s whole argument, the one he’s been making since Strange Loop talks that became mandatory viewing for a certain generation of developers, is that we conflate simple with easy. Easy means familiar. Easy means close at hand. Easy means I can get started in five minutes. Simple means not entangled. Simple means one concern, cleanly separated from other concerns. Simple means you can reason about the thing.
These are not the same. And we spend most of our careers choosing easy and calling it simple.
What struck me watching the documentary is how deliberate Clojure is. Every decision has a reason. The immutability isn’t there to make you feel virtuous, it’s there because mutable state is a source of complexity that compounds over time. The emphasis on data over objects isn’t aesthetic preference, it’s a bet that plain maps and vectors are more composable, more visible, more simple than class hierarchies.
Even the parentheses, once you stop grimacing, are actually simpler than the syntactic noise of most languages. There’s one way to call a function. That’s it. You don’t have to remember which bracket goes where.
Simplicity is a choice. And it’s a hard one, because easy is always right there.
What That Means for Coming Back
Here’s the thing about returning to Clojure in a confused haze of deps.edn: the discomfort is part of the deal. It’s not a bug in the re-onboarding experience. It’s almost the point.
The tooling gap I feel with deps.edn vs Leiningen? That’s me reaching for familiarity when I should be reaching for understanding. What does this alias actually do? Why does deps.edn compose the way it does?
Once I stop mourning Leiningen and start actually reading the deps.edn model on its own terms, it makes sense. It’s simpler than Leiningen, actually. It’s just not easier.
Clojure has never been interested in being easy. It is deeply interested in being simple. And that means every time you feel that friction, can’t I just have a mutable variable here, can’t I just do it the way I did it in Java, Python or Go, I can’t get the tooling just work like I expect. Is this friction pointing to something genuinely complex in the problem? Or are you just attached to a familiar way of introducing complexity?
That’s a confronting question. It’s a good one.
The Path Back
I’m not going to pretend I’ve fallen back in love yet. We’re still in the awkward re-acquaintance phase, long silences, occasional moments of the old warmth, a lot of consulting documentation.
But I remember why I loved it. The REPL-driven workflow, where you grow a program incrementally and every function is immediately testable, is still unlike anything else. The insistence on data, just data, not objects, not classes, just maps and vectors you can inspect and manipulate and pass around. It still feels like a genuine insight about how software should be built. The community, small and deliberate and philosophically coherent, still feels like somewhere worth hanging around.
And “simplicity is a choice” is sitting with me in a way that’s going to outlast the tooling confusion.
Most of the complexity in the software I write is complexity I chose without realising I was choosing it. Mutable state I didn’t need to mutate. Abstractions I built because building abstractions felt like progress. Dependencies I pulled in because they were easy, not because they were simple.
Clojure is an invitation, a demanding, parentheses-heavy, sometimes-infuriating invitation to choose differently.
I’m going to try to take it. I just need something to build…..

