Clojure Rationale (2008)
clojure.org
clojure.org
I've been using Clojure since 2008 and I've been running a single-founder business (SaaS) using Clojure and ClojureScript for the last 8 years. I could not have succeeded without Clojure.
From what I observe in online discussions, the biggest advantages are ones that young programmers do not appreciate :-)
* backwards compatibility: I don't have to deal with language-caused breakage
* fantastic environment: the JVM received bazillions of man-years of development and I get the benefits of a great compiler and a choice of fantastic garbage collectors
* mature community: no drama, just getting work done
* single language for server-side and client-side: most of my model (business logic) code is cljc, and gets used in both places
* no need for external serialization formats like JSON when sending data to the client (use EDN)
* not a single concurrency-related bug over 8 years
* eliminates most template/boilerplate code: nearly all code that I write is directly related to functionality
As for actual "language features", I also value different things than most commenters:
* macros are very useful, but I don't use them often. I have less than 20 in my entire code base.
* transducer pipelines are a fantastic tool to structure the application and promote code reuse, with great performance as a free side benefit, I feel like they are hugely underrated
* core.async is really useful once you get to asynchronous processing
There are also some nice practical advantages, like ClojureScript being compiled in advanced mode using the Google Closure compiler (a free performance boost!).
There is no "magic" to Clojure. It's just another programming language. It isn't revolutionary. It isn't hip or fashionable. It doesn't write your code for you. But it has a number of small improvements and niceties, which taken together result in a huge difference when writing real-world large applications.
Most importantly, when I look at my day to day work, I spend very little time on writing actual code, and I don't have any boilerplate or repetitive code. I spend time trying to understand customer workflows and thinking about how to model and represent these processes. In other words, GPT code generation isn't taking my job anytime soon.
My advocacy is because I'm quite happy where I am, and I owe a large part of that to Clojure and ClojureScript. These tools make it possible for me to manage an application of this size and complexity.
Yet I'm happy I tried it, learned a bunch of stuff along the way.
When you need them, you need them :-)
I never quite bought into the atoms/transactions concurrency model, but probably wouldn't have looked so closely at hashed tries if they weren't clojure's choices and those have brought me a lot of joy.
But, agreed, it has gotten better.
For the immediate, REPL-based development flow, a VM is a great host platform.
I see JS/TS going stronger than ever, Java and .NET still very strong and growing, Python again stronger than ever, WASM on the rise.
What's on the "compiled" side, apart from probably Rust making headlines on HN? What are the major products or services written in Rust? What are the unicorns with Rust secret sauce?
C/C++ is still strong, but is it expanding? Is Go even in the "compiled" camp?
When was the last time you saw an interpreted language as a new language come out in the last few years?
"Memory and other resource management" Can people really claim they manage memory and resources with a low-level language when their 30-line YML configured cluster reallocates whole machines at a time?
I use Erlang as my main language. I like that so many languages have lisp alternatives, so I can just rename the most common function calls to what I'm used to, and feel mostly at home between the different languages, other than different syntax for some data structures like maps.
I don't know where you are sampling your Lispers from. The only people I see blindly opposing OOP in Lisp communities are people who either (1) don't write a single line of code, or (2) know nothing about Common Lisp, the various Schemes with their own object systems, or even pause to consider what inspired Clojure's `defmulti` (spoiler: a Common Lisp library that used the Metaobject Protocol to allow for arbitrary dispatch in generic functions).
With that said, I do notice the Clojure community tends to be more against OOP than other Lispers, which I find golden because, again, the core language has things directly inspired from MOP libraries, and things like "atom watchers" are trivially an :AFTER method in CLOS, and so on.
Elsewhere in Clojure, he makes his preferences the defaults (like immutability over mutability), but always has an escape hatch when necessary. For inheritance, there's no escape hatch. Best you can get is a crippled proxy.
Another issue is how mutable fields in deftype work. Mutable fields can only be mutated from class methods (protocol fns in Clojure parlance), so you can't use outside helper fns. You can add helper fns to your protocol (like an interface), but that's a public signature, not generally meant to have internal-only fns.
The joy of interop with Java from Clojure is occasionally getting to discover that there's no good code reuse in certain situations with a family of classes, and realizing, oh yeah, this is why we wanted inheritance in the first place.
You can use gen-class here. Granted complex Java interop trends toward a point where it becomes easier to write and expose a Java library; the option is there though.
Secondly, what he added is enough for doing OOP in Clojure, in fact, very few OOP languages support everything that CLOS allows for, and that doesn't make them less OOP.
OOP !== Java 1.0
And my complaint is that unlike many other places in Clojure, there's no easy escape hatch for inheritance when you need it. `proxy` is limited, and `gen-class` involves AOT compilation, which can cause various problems.
note though, that Lisp was 1994 the first officially standardized object-oriented language.