Clojure effectively is Java, they share the same ecosystem. The only differences are the syntax, which is really just cosmetic (being much terser than classic Java is nice) and Clojure being highly opinionated about semantic style (ie, you should be coding in the style of a very specific expert developer named Rich Hickey).
This sounds very bitter. Also, having worked in multiple places where Clojure is the main language, I don't agree at all. Most places make their own coding rules / standards, enforce them with linters and custom formatter rules. Also the biggest difference by far isn't the terser syntax, it's that Clojure is a immutable, functional language, and Java is the exact opposite.
What part is bitter? I mainly develop in Clojure, Rich Hickey is a genius and more people should program like him.
> Clojure is a immutable, functional language, and Java is the exact opposite.
Program in an immutable, functional style is possible in any language. It won't be as good as in Clojure, and if someone wants Clojure's style they should use Clojure. But that won't stop anyone who wants specific properties. I personally am happy to be writing code that is Clojureish in any language people want to pay me to use.
Regardless of that, the interop between Clojure and Java ecosystems is as close to perfect as can be achieved; they're basically the same circle on a Venn diagram. There is no risk of Clojure having a different deprecation schedule compared to Java.
It is so not. Clojure is to immutable-functional as Prolog is to logic: a procedural language with fancy syntax and funny execution order, masquerading as the other thing.
It's built on the JVM. How could it be otherwise? Sure, you can program in the immutable-functional style in Clojure, but under the hood, it's procedural. You have to deal with all the same procedural issues: the compiler doesn't really smooth anything over for you.
> This sounds very bitter.
This is bitter. But I thought what you replied to praised Clojure.
The examples you just created are unidiomatic Clojure. Is that supposed to somehow convince me? I have yet to see anyone actually use `while` in Clojure, and redeclaring `def`'s is also not something I've actually ever seen, despite yes, it being possible to write horrible code if you really set your mind to it.
> The examples you just created are unidiomatic Clojure.
Assuredly. Yet, in an immutable-functional language, the examples I gave are unrepresentable. Clojure has nice syntax, like recur, to make it easy to write pure functional programs, but ultimately it's a procedural language full of side-effects, with a fairly simple mapping to JVM semantics.
Clojure is often the right tool for the job, and I'm sure the Clojure programmers reading this are thinking things like “a simple mapping to JVM semantics is not a bad thing!”. But mere usefulness doesn't make it Agda.
Isn't Clojure dynamically typed by default? That would seem like a major difference to Java.
Or is enterprise Java effectively dynamically typed as well, so that the language-level difference matters less? I had only very limited exposure to JEE, and was surprised how much that was nominally unchecked at the Java language level was effectively type-checked by the JEE platform. But maybe this falls apart for non-toy projects?
Clojure is statically typed - in practice everything is a java.lang.Object. Checkmate, type system enthusiasts >:D. Except macros, I suppose. If you try to pass function arguments that aren't a Java object or primitive IMO it won't work. [0]
More seriously, if you want something with type T, Clojure can give you something with type T. It understands types. Doesn't respect them, but it understands what it is ignoring. It isn't trying to replicate Java, but it has all the tools to replicate Java if necessary.
[0] The author acknowledges that this paragraph, while true, is unhelpful. It is offered in a wry tone.
Java doesn't have macros, so everyone uses reflection. That moves errors to run-time. Add to that the typical enterprise patterns like dynamic dependency injection and you end up with very dynamic deployments.
I understand that. The build environment I used had type-checking for CDI annotations, obviously outside of the Java language, if I recall correctly. If the types did not line up, the build would fail. This was part of some JEE training I took out of curiosity, maybe real-world JEE is different?
There's Java interop, a bit like Rust has C interop, but the Clojure sw ecosystem and culture is quite distinct from Java's. So I'd revise your characterisation to: different syntax, different semantics, different ecosystem, different culture.