Yes, but it’s really not the same as first class static typing support. It also doesn’t help when none of the libraries you use have type annotations and when I last looked it was also quite slow.
This is a great article, and I think does a great job of surveying the landscape as it stands. Particularly great to hear reports of ease in hiring and training, which doesn't surprise me, but is nice to be able to cite when risk-averse tech leads express concern about staffing and team-scaling.
I find it somewhat funny that a lot of the critiques here are about purity or types. I really see it as Clojure's core strength that it's both pragmatic and approachable. I'm a math/alegbra nerd, so I love languages like Haskell & OCaml, but they're much more austere for the uninitiated, and have had their own troubles growing. From my experience, the approach of Clojure spec is really nice because it gives you more flexibility/freedom/support in both thinking at a high level about the design of your system (in spec code) before you actually write the (implementation) code itself, while also not requiring it, and letting you add after the fact. You also get a lot for it: generative testing, destructuring, documentation, etc.
That having been said, I'm surprised that more of the pro-type folks here don't seem to be familiar with the [typed clojure](https://github.com/clojure/core.typed) project, which adds optional typing, along the lines of Racket's contract system. To me, it's one of the great testaments to the power of Lisp that you can fairly easily implement types on top of the core language.
My one beef with this article is that scripting with Clojure is now not only possible, but a joy, thanks to GraalVM and [babashka](https://github.com/babashka/babashka)! This has made a HUGE difference in the surface area of problems to which I'm able to apply Clojure.
I did mean "homoiconic". It was 5am when I wrote it.
> I don't find it difficult to intertranslate at all.
I should have also mentioned "variadic" with regards to lists and macros. Although it's possible to inter-translate, the required add-ons such as Template Haskell macros and Typed Clojure make each language more clunky. The pure form of each language is based on two mutually exclusive foundations, i.e. strongly typed auto-curried parameters and variadic untyped macro parameters.
Many macros can be translated to Haskell due to laziness. It's true that these can be difficult to translate or end up requiring TH. That's a downside, but it's rare.
And variadic functions are easily translated as well. They're much more syntactic convenience than true semantic variation. Typically, variadic functions encode defaulting which, in Haskell style, is just ignored. Otherwise, you just encode them as separate functions with different names. That can be annoying, but in my experience it rarely is. Worst case, you can often abstract over most of the polymorphism using a typeclass.
I'm sure you could manufacture some Clojure code which takes advantage of non-obvious macros, bizarre variadicity, and massive dynamic typing... but it'd be really hard to understand as a human.
Human intelligibility tends to drive Clojure code to be easily translatable.
https://github.com/clojure/core.typed
To me, it's one of the great testaments to the power of Lisp that you can bolt on a static type system after the fact.