> What is mutable by default in Clojure? Nothing.
All data in Clojure inherits from java.lang.Object. I get what you’re saying, but in real life commercial projects, especially when you use libraries and Java classes, the code ends up with a lot of mutable things. You can never know if any function you call does mutate something without keeping all definitions in your head, and with 20+ people on the project, this is a challenge. Programmers of languages less sexy use frameworks to manage state and effects, but not in FP, which clojurians think they do.
> Imperative? What is imperative by default in Clojure? Nothing.
Please note that I’m not praising Common Lisp or Racket either - the same criticisms apply to them, except they ship with type systems. In Clojure IO is usually done by calling a function that does some (blocking) effect and returns something. That is programming in imperative style. In practice effectful functions find their way into programs, and taints everything referring to it. For this reason, clojure programs written by teams tend not to be as FP.
> Blocking IO. Ok. So you want JavaScript?
I for sure prefer to write a backend where no teammates ever introduce blocking calls. I once worked on a webpage which took minutes to render, because of blocking calls on the back end. It was a mess, after having been worked on for years by around 70 coders, including consultants for the biggest names in Clojurespace.
> Zero guarantees at compile time. Almost true.
Except for syntax errors.
These things turned me off: imperative and blocking IO and effects and no square framework to contain it, combined with zero compile time checks. It results in teams making bespoke solutions that other teams in the company (or even consultants from the famous players in the Clojure space) solving their code needs by meeting with the authors and asking for changes, having a ton of testing to make sure it does not fail in rare code paths, and having one guy on every team religiously adding specs in order to not go mad.