I've programmed in dynamic languages for most of my career (about a decade now), and have always missed types. I picked up OCaml (Reason flavoured) recently, and I've been able to enjoy the Hindley-Milner typesystem without worrying about side-effects with complex types, since OCaml is a fine mix of imperative and functional programming.
Language preferences are usually framed as an objective measurement, but I've always found it to be based on our personal experiences. Since you've been doing a lot of Java, I'd surmise that the clean, functional yet dynamic nature of Clojure with Java interop is appealing to you. Me on the other hand has been burnt enough times with dynamic systems that keep shifting from under your foot (Ruby metaprogramming), test suites that makes refactoring more difficult (it provides safety, but the manual labour is unforgiving), and a general sense of dread everytime I put systems into production. But more than anything else, the biggest pain has been the sheer difficulty to refactor growing codebases.
Large dynamic systems, if they manage to not crumble from the inside, usually gets hammered by a sweeping change in external reality (terminology changes, shifting of levels in domain hierarchy etc.). When there is a pressure to ship we add a new mapping without touching existing naming, and slowly the domain names in the system exhibits a tangled relation with the actual domain.
That's just been my experience, and so I'm here learning me some good old OCaml and being very happy with what I'm getting out of it.
Have a look at Spec and the design philosophy behind it if you are still interested in Clojure at all. Especially how Hickey feels about open specs, versioning, and names. It is a pretty opinionated stance to take on solving those issues, but it convinced me and I no longer have the worries you describe about the dynamic nature of a large Clojure system.
I've programmed in dynamic languages for most of my career (about a decade now), and have always missed types. I picked up OCaml (Reason flavoured) recently, and I've been able to enjoy the Hindley-Milner typesystem without worrying about side-effects with complex types, since OCaml is a fine mix of imperative and functional programming.
Language preferences are usually framed as an objective measurement, but I've always found it to be based on our personal experiences. Since you've been doing a lot of Java, I'd surmise that the clean, functional yet dynamic nature of Clojure with Java interop is appealing to you. Me on the other hand has been burnt enough times with dynamic systems that keep shifting from under your foot (Ruby metaprogramming), test suites that makes refactoring more difficult (it provides safety, but the manual labour is unforgiving), and a general sense of dread everytime I put systems into production. But more than anything else, the biggest pain has been the sheer difficulty to refactor growing codebases.
Large dynamic systems, if they manage to not crumble from the inside, usually gets hammered by a sweeping change in external reality (terminology changes, shifting of levels in domain hierarchy etc.). When there is a pressure to ship we add a new mapping without touching existing naming, and slowly the domain names in the system exhibits a tangled relation with the actual domain.
That's just been my experience, and so I'm here learning me some good old OCaml and being very happy with what I'm getting out of it.