21 comments

[ 0.19 ms ] story [ 39.6 ms ] thread
> A bigger problem is the tedious necessity of having to reconstruct the desired state every single run. When you have something small with limited functionality, that is fine, but as your application grows, rebuilding the state can take a significant effort.

This is what tests are for. There should be no buildup of internal state that can't be arrived at with a simple invocation in a unit test.

Tests help to a point, but anybody who's worked on a large project knows that unit tests miss a lot of stuff because they don't focus on end-to-end relationships in code. There's a whole genre of memes about having unit tests and lack of integration tests for example. Of course you can add, integration tests, and regression tests, and so on. And you should, but doing that in the middle of you figuring how to best implement a particular feature is a lot of drag.

Often, when you're building something new, you're not sure what the best approach is. So, you need room to experiment and try different things to see what works best. Writing tests boxes you into an approach out of the gate.

Sure but do coding agents need this? They can create fixtures or scripts very quickly. No offence, but this article reads like a list of reasons you like Clojure.

I like many of the ideas in Clojure, but I never learned it, so it doesn't matter to me what advantages it provides to an agent if I can't understand the code its creating. This year I've done a lot of work modifying open source applications I use with agents, some in languages I don't know. One is Metabase, which is written in Clojure. Another is Forgejo, written in Go. I had no real experience with either language.

Go was much, much easier to understand in that context. I could review the agents changes and follow data flow, follow tests etc.

And no, its not because I'm more familiar with similar imperative languages. The last 14 years I've written the most code in Elixir and Haskell. Lots of Javascript, C++ and Python as well. Admittedly no Lisp other than a bit of emacs but semantically Elixir is probably closer to Clojure than most Lisps are.

In my experience they do. I use LLMs a lot, and one of the most common failure modes I see is that they implement stuff, but fail to wire it up end to end, or don't consider the broader context. The features of Clojure I outline in the post directly addressed the failure modes I've experienced using most other languages.

In fact, I've actually tried using Python and Js with LLMs initially because my logic was that these languages are more widely used and there's more training data. It's been a miserable experience for me, and I'm having a much better time with Clojure. I'm sharing my own experience here having actually used both types of languages, and the benefits I see in my workflow.

The fact that you're unable to learn Clojure is very much a you problem. I worked at a Clojure shop a while back where we hired university students regularly. They were able to pick up Clojure within a week or two and write useful code with it. The fact that somebody with over 14 years experience can't learn this language is absolutely surreal.

I never said I can’t learn it. I said I haven’t.

My point is for someone who hasn’t learned the language, Clojure is one of the most inscrutable languages you could choose to use with an agent, and I doubt people who don’t know it will put the time in at this point. I’d expect exactly the same is true of Haskell. I know it well, so sure I can use it with AI, but I wouldn’t expect many will learn it now.

Inscrutable to you does not imply inscrutable to everyone. Haskell is a different beast since it has to type check everything in a fine grained way.
I haven't written Clojure in a while.

but I think clojure is well suited for the age of llm's. token efficient .everything is data even the code is data is easy to deal with verification. pure functions etc.

however one will still need to know how to write / read clojure. when the industry is trending towards not reading code e.g the shit dhh has been parroting lately about not reading code and likewise many people in the industry.

Right, hence my pitch is that people should actually learn Clojure. You still need to understand what the code is doing, but there's a much bigger case for using a high level language that's concise and expressive with LLMs around.
Not necessarily, unfortunately.

Just today I got some project discussion related to Alokai (https://alokai.com/).

With platforms like this one, the whole programming is done in natural language, and the same attention given to the generated code, as most folks look into the Assembly output of their compilers.

This is now the trend across all SaaS products with extension points, the old SDKs are now legacy, or specific MCP tools, the new way is "agentic".

I think this kind of stuff will work for certain domains, but there are limitations of what you can do in terms of defining complex behaviors using natural language. I expect there are still going to be plenty of software problems where you do need to be far more hands on. A formal description will always be more precise at the end of the day.

What I expect will happen is that we'll move more towards creating specs and contracts as developers that the LLMs will fill. And this works great with Clojure.

For example, I've been working on this library which lets you specify the state graph and constraints https://github.com/jlt-commons/writ

And I used it to formally encode Erlang OTP specs in a machine verifiable way here https://github.com/jlt-commons/ensemble/tree/main/test/ensem...

All I can say is best of luck to anybody trying to do something like that using natural language.

I love Clojure's Flowstorm, it makes it easy to verify code is doing what you think — all the data is exposed programmatically so you can also create your own GUIS from it or feed it to LLMs so they can have a deep understanding of program behaviour (or you can browse it yourself)
Making GUIs with Clojure watching it render in real time is quite an experience.
> There are, however, a few drawbacks to the Java virtual machine, which Clojure traditionally runs on. From my experience, many developers, fairly or not, have an issue with requiring the JVM, and shy away from Clojure because of startup time, a somewhat heavyweight runtime, and perceived bootstrapping complexity.

This used to be discussed in the past and it has been proven that the culprit is the clojure implementation itself, the work done during startup, that regular Java code doesn't do, or can even take advantage of JIT caches/AOT.

"Why Clojure starts up slowly — is it really the JVM?"

https://ericnormand.me/article/the-legend-of-long-jvm-startu...

"Clojure's slow start — what's inside?"

https://clojure-goes-fast.com/blog/clojures-slow-start

"Why is Clojure bootstrapping so slow?"

https://blog.ndk.io/clojure-bootstrapping.html

"Babashka: How GraalVM Helped Create a Fast-Starting Scripting Environment for Clojure"

https://medium.com/graalvm/babashka-how-graalvm-helped-creat...

But the myth stays, because everyone has opinions based on perception.

Anyway, great to have Jolt as an option as well.

[dead]
> the JVM isn't the only reason Clojure starts slowly, but it's still a major contributing factor

In case you didn't actually look at the links, but the evidence seems to point to this not being true (JVM startup is ~10% of the time)

> you're still hauling around a heavy runtime

> around 8 to 13 megs in size

I think if you jpackage a Clojure app with no GUIs or anything (that then bundles only the strictly necessary parts of the JVM) - it's around 50MBs. It's still embarrassingly slow to launch, involves ugly installers, doesn't provide crosscompilation and the memory usage makes Electron apps look lean.

That's to say, I think Jolt has a very valid place in all of this :) If I could plug in Clojure code and get out small fast executables for all major OSs (cosmopolitan?) that I can then share, that'd be useful for the rare situation I don't have any JVM dependencies

I have yet to have a good experience with any JVM based app on the desktop with or without Clojure. Take a look at something like in IntelliJ as an example. It doesn't have a Clojure runtime, and it takes forever to start using gigs of memory. Like you said, it makes Electron apps look lean. I ended up switching to using VSCode because it just runs a lot better and uses less memory. And when it comes to Clojure specifically, ultimately it doesn't really matter whether the slowdown is JVM or Clojure specific. This problem has existed for around a decade now, I'm not expecting that it'll be addressed in the foreseeable future.

And yeah, Jolt solved this problem for me completely. Startup is fast, you get a single binary, and it runs anywhere Chez Scheme runs which is mac, Linux, Windows, Android, and iOS. The best part is that you can use FFI to access native ecosystem as easily as Python.

There's also some fun Burin's been working on porting OpenLdk to Jolt https://github.com/jlt-commons/jolt-openldk

It might make it possible to translate Java bytecode to Jolt, and then link it into the binary similarly to native libs as a statically linked fasl. That way there might not even be much of a runtime cost.

very cool!

and yeah, I dunno what's with Java apps being clunkers haha. I've come across games in Java that didn't feel bloated, but for some reason desktop apps almost always have a certain bloated feeling to them. Though I feel the same with Electron/VSCode (the input delay to me is very noticeable)

thank you for the work you do :)

It's actually fun to read the code for Java games, people tend to do all the allocation up front to avoid GC pauses. So, it's a very unique style. :)

Very much agree on Electron, there is a noticeable lag, and it's always bothered me that making a native app has become such a chore that people now just package a browser to render the UI.

And thanks, it's always nice to hear that it is useful and appreciated. :)

Curious what your thoughts on Jank are? I’ve been waiting for it to mature for ever because I see really strong benefits here in being able to use Clojure as an actual everything language by being able to bind to native libs without going through Panama.
I've been following development Jank for a while, and I think it's a really exciting effort. But it's not really easy to get up and running with at the moment, and there are some gaps, such as lack of protocols, which preclude many existing Clojure libraries from working on it.

My understanding is that the main aim of Jank is to facilitate game development through tight integration with C++. And I think it's done some very interesting work on that front with the ability to generate LLVM bytecode on the fly. But it's not aiming to be a drop in replacement for Clojure.

So, I'd say that Jolt and Jank serve slightly different niches. My goal is to be able to build native binaries, have relatively good performance with fast stratup time, reasonable memeory use, and a high degree of compatibility with the JVM Clojure to run existing Clojure libraries. Jank appears to be aiming to be a highly optimized language bringing Clojure semantics to the C++ ecosystem.