Clojure marries the elegance of Lisp and functional programming with an extreme practicality. The practicality of it is precisely _why_ it is hosted on the JVM ecosystem.
There is this very common reaction to Clojure (also reflected throughout the original post): a balking at its pragmatic decisions. But Clojure's pragmatism is precisely what makes so significant and wonderful.
My issue isn't that. its that every Clojure project I've seen has always been at Java Shops, where eventually some java dev decides it too hard/ doesn't have the time to learn Clojure, and it just gets rewritten in Java. I've seen this happen with a few Scala projects as well.
That's true, but the other way is also true, nobody would adopt Clojure at a professional shop if it wasn't for an existing Java shop where some devs thought they'd rather use Clojure and started adding Clojure progressively to their existing stack.
There's plenty of professinal shops that aren't Java shops to begin with. There's also plenty of professional multi language shops that aren't JVM shops as well.
On multiple measures Clojure is the most used Lisp, while also being the youngest, which I think speak a lot to the adoption benefits of being on the JVM and on JS.
Maybe it'll bite it long term, hard to say, but it definitely allowed it to quickly catch up to CL and Scheme and pass them in popularity and adoption.
The JVM ecosystem pioneered a lot of what I see as awful anti-patterns in language development:
- Language-exclusive build chain: Not that Make is the be-all and end-all of build tools but it worked with everything without prejudice. To understand the basics of a build system, you only needed to know one tool. All attempts at fixing Make's flaws fail to understand this fundamental recipe for success. Now when you switch languages, you need to relearn that layer on top of the language itself. And the tools all do the same thing but with their own syntax, commands, and eccentricities.
- Language-exclusive packages and repositories. Once upon a time, you learned your OS's package manager and you were done. Now you need to learn a new package system for every language out there. Again with their own syntax, commands, versioning, and eccentricities.
- Needing language-aware parsers to determine dependencies. You can't depend on spatial locality or compiler-output dependency trees to know whether to rebuild, reinstall, etc. You had to parse out the org.whatever's and resolve that back to a jar or class, which was clumsy and mostly wrong.
- The OS doesn't know how to run your program. What's so hard about building your executable so it can be natively run by the OS? Everyone has to write the same `#!/bin/sh exec java -jar ...` wrapper script. Java programs worked best by assuming it was going to be a pariah hanging out in /opt and never actually integrate with anything.
- Runtime versioning and installation was painful. I disliked having to suddenly manage environment variables just to run something. It continues today with python2 vs python3, GOPATH, etc. On top of that, JRE's weren't a simple "curl|bash" and no one was allowed to repackage the JRE to make it more user friendly.
I'm not sure I agree here. Bazel / Make / Ninja still exist. Most of the tooling that exists extant to that usually leverage some knowledge of the conventions of both the community as well as actual knowledge from the code itself (Cargo for example understands the module system in Rust). You kind of touch on this by mentioning "language-aware parsers" for dependency management, but this existed in C and C++ long before the JVM came along, so it's weird to place the blame there.
Make has many things wrong with it but I wouldn't say that a "one build tool to rule them all" is something it did well. Even with stuff like CMake or GNU Autotools the final makefiles are almost exclusively used for C projects. I rarely see Make used in any other context, which I'm not convinced is a machination of language-specific tooling rather than some intrinsic property of Make itself.
> Language-exclusive packages and repositories
The proliferation of packaging systems is frustrating, but would you rather learn pip (PyPI) / cargo (crates.io) / npm (npmjs.com) across several OS's and platforms or learn 5 different OS / platform package managers? I know for certain there's nothing like that on Windows!
This isn't the JVM's fault, and I think you're looking at it in the wrong order here. These language-specific package managers and repos are made to make the language run consistently in different environments. Most repository maintainers do not and cannot have the bandwidth to package everything under the sun for every programming language.
> The OS doesn't know how to run your program
Oof. The program you're running is the JVM, which as an input is taking a jar file and as output does some work. The OS knows how to run that just fine. Doesn't this criticism basically disqualify every single useful program that isn't a compiled C binary on Linux? ELF isn't that hard but also I'm not sure we need to tie all our boats to that sail either.
If I'm trying to be charitable, I think you're experiencing a lot of frustration with your tooling and expecting something out of the JVM and programming in general that isn't necessarily true. You may just want to stick to C / C++ and tooling built 40+ years ago, but dismissing most of the tools that people use every day seems a bit "cut off your nose to spite your face."