> If we used interop for everything mundane, Clojure would really just be an S-expression shaped husk over Java code. Not a very good solution.

Interop into the host system in Clojure is idiomatic. I think often there is a misunderstanding of the difference between information systems and artificial ones. Rich Hickey gives a plain english explanation in section 2.1 of his fantastic talk "A History of Clojure". [1]

I have been using interop into Java for the mundane for ten years. Our general approach is to simply use p/datafy to convert the result of interop calls immediately back into Clojure datastructures.

I don't find that approach onerous and it doesn't impact our overall system design any more than using a third party DSL. The interop ensures we take ownership of our Java dependencies rather than using an outdated thin DSL wrapper which provides no real value anyway (as I assume the Stripe example would be). In the past where I've worked on projects with those wrapper DSL I tend to throw them out, they're the wrong idea.

In my case I use stable, mature, artificial systems provided by Java to underpin my application. My application is an information system, where I use the lean power of Clojure to implement complex functionality without the drag of Java.

The result is an echo of the Destroy All Software talk "Funcational Core, Imperative Shell" [2], but rather more a "Data-Oriented Core, Type Oriented Shell". The end goal being to enable my small team to ship better and faster than our competitors

The most important artificial system in our application is Jetty, the networking framework. The next is the Kafka Client / Streams API. That's our Type Oriented Shell. The magic of the application is Clojure, everything in between. The glue is interop, p/datafy, and transit.

In some cases the magic, value-adding, bespoke software part a developer is attempting to add between the Type Oriented Shell parts is tiny, and the result feels like an S-Expression shaped husk. In my case that magic part is enormous, and the benefit of using Clojure obvious.

If you are shipping an information system, the problem domain is non-trivial, and you are delivering on the JVM, I believe you should use Clojure to attack that problem. For me it has been game-changing in terms of pace and quality of delivery. Right tool for the right task.

Clojure is also enormously more fun and liberating to work in than Java, and you shouldn't underestimate the power of joy as a morale maintainer when working on one problem for a long time. I first started working on our product in May, 2018 and I enjoy working on it today.

For context, I worked in Java for 15 years before adopting Clojure a decade ago so I understand the relative benefits of shipping production information systems in both languages. I'm also probably more comfortable just using Java interop than some Clojure developers.

We have plans to open-source the useful parts of our type-oriented shell and the glue that binds them in the next few months, along with our solution for managing dynamic system state, but then again I've been faintly promising that for three years so take it with a grain of salt.

The application I work on is enterprise-grade tooling for Apache Kafka: https://kpow.io/

[1] https://download.clojure.org/papers/clojure-hopl-iv-final.pd...

[2] https://www.destroyallsoftware.com/screencasts/catalog/funct...