Great call outs Alex. I especially think #2 and #3 are the most important ones to people in my experience.
Every time I’ve tried to influence others to pick Clojure it came down to #3 as the first criteria, and #2 as the second criteria.
Now to be honest, I think Clojure could improve when it comes to Ease of Development and Refactoring. I think it is true that Clojure is harder to follow along what keys are available where, what entities exist and what data do they contain, where are they used, etc. I think it’s also true people struggle to figure out simple things, how do I run code? How do I setup and use a REPL? How can I setup tooling to have proper auto-complete? How do I know my syntax is correct? Where is this function used? Where is this piece of data used? I’ve seen people struggle with things like How do I loop? even. For refactoring people have similar issues, how do I find each things that depended on the thing I just changed?
The tooling has definitely improved, but I think their discoverability and getting started/learning curve is still a struggle. And for some of the other challenges, that’s inherent to how the language is today in some aspect. It’s hard to answer the question “What depended on the thing I just changed” when dependencies are sometimes dynamic or generally difficult for tooling to keep track of.
For me the keyword here is “Ease”, those things are harder in Clojure, but they can be done and you can learn to manage it by becoming better at using Clojure.
That said, that lack of “ease” I’m pretty sure is responsible for almost all people who try Clojure and decide not to use it, or who hesitate to learn or work with it.
I think it be interesting to discuss more what could be done around this, and is there a way to make those things easier without trading away other good properties of Clojure?
Static types can be one solution that makes some of this easier, but it also seems to trade too much of what makes Clojure what it is away. Gradual Typing might be a middle ground, but it’s no easy task to add such a layer and find a way to do it that complements Clojure nicely and doesn’t just add friction. I’m curious what else could be done here as well.
Edit:
Some of the things I think have improved on those in recent years are:
- Schema/Spec/Malli
- clj-kondo
- Clojure CLI and tools.deps / tools.build
- The Orchard with nRepl / middlewares / Calva / Cider / Cursive, etc.
- REBL / Portal / Reveal
- Shadow-cljs
- Figwheel-main
- Babashka / nbb / sci