Clojure in the age of language models

(yogthos.net)

39 points | by silcoon 2 days ago ago

20 comments

  • pjmlp 13 hours ago

    > 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.

    • yogthos 9 hours ago

      You're right that Clojure's own bootstrap is a huge part of the startup cost and it's not just JVM bad. But I'd push back a little on the framing that the JVM gets blamed unfairly because the JVM still does have a real startup hit compared to something like a Chez Scheme binary.

      Chez and produces native binaries with startup in the microsecond range and around 8 to 13 megs in size. That's not just slightly faster than JVM Clojure for cold starts. The JVM is designed around a model where you have a long-lived process like an app server. Even if you optimize Clojure's bootstrap down to zero, you're still hauling around a heavy runtime.

      And GraalVM native-image comes with its own set of trade-offs since it's based on a closed-world assumption, which means dynamic class loading, reflection, serialization, and so on all need to be configured at build time. So, you can't do eval at runtime, and Babashka ends up having to use an interpreter for anything dynamic. Bytecode isn't available at runtime either, so you lose a bunch of the debugging and monitoring tools as well.

      The compile time is also brutal. Last I tried making native-image it took several minutes to build, and you have to be careful with how you write code or what libraries you use. It's not just a different compile target that works as a drop in. There's a significant cost if you're iterating that quickly makes you miss the REPL.

      So yeah, the JVM isn't the only reason Clojure starts slowly, but it's still a major contributing factor. Also, as I point out in the post, there are lots of negative connotations with JVM in the broader programming community. People have been preaching that the JVM is not a problem for years now, but it's still shunned. An perception is just as much a barrier as a technical limitation.

      Jolt shows what's possible when you drop the JVM entirely.

  • charlotte-fyi 5 hours ago

    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.

    • yogthos 2 hours ago

      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.

  • slifin a day ago

    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)

    • giancarlostoro a day ago

      Making GUIs with Clojure watching it render in real time is quite an experience.

  • mrkeen 2 days ago

    > 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.

    • yogthos a day ago

      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.

      • jeremyjh a day ago

        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.

        • yogthos a day ago

          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.

          • jeremyjh a day ago

            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.

            • millettjon a day ago

              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.

            • yogthos a day ago

              Having built a ton of software with agents using Clojure that's huge news to me. Seems like you've already made up your mind though, so it's clear that you don't care to learn from people with actual experience or have a rational discussion on the subject. You do you.

              • jeremyjh a day ago

                I probably haven't expressed myself well. Your experience with Clojure is exactly the reason you haven't experienced what I'm talking about.

                If you haven't used Haskell, I'd encourage you try to adding a small feature to an application written in it, such as Pandoc. Tell the agent what you want, then try to understand what it did.

                Personally I love Haskell, but I think its over with in the age of agents. People will not put the work in to learn it because telling the agent it to do it is so tempting, but you've really got to struggle with it quite a lot to get over the initial hump.

                • yogthos a day ago

                  If you actually bothered reading my post, you'd see that it is about why it's worth learning Clojure. Nowhere am I suggesting that you should let agents run wild on a language you aren't comfortable using. And the only people I've seen actually struggle with it are largely those who're deeply invested in the imperative style.

                  I actually started my FP journey with Haskell, and I found Clojure very easy to pick up after learning it because most of the concept transfer directly, and it's a much simpler language. If you love Haskell, I'm very curious what challenges you ran into that students I worked with, who had little to know programming experience, didn't.

                  I fully expect that people will, in fact, continue to learning new languages going forward. And my bet is that people will see value of working with high level languages like Clojure in agentic workflows. Imperative languages focus on low level details which are precisely what the LLM is great at automating. Languages like Haskell or Clojure focus more on declarative logic, and that's what the developer will need to understand going forward. But the advantage Clojure brings is the live environment which speeds up the development loop.

                  Your thesis appears to be that the language doesn't really matter when the agent writes code, but that couldn't be further from my own experience. I find the agentic workflow with Clojure is far superior to anything else I've tried for the reasons I articulate in the post. I built a large Rust app using LLMs, and all I can say is I'd never touch Rust again if I can help it. https://github.com/dirge-code/dirge

                  And of course, people have been talking about the demise of Lisp since before I was born. Yet, it's still here, it's still as useful as ever. And I doubt languages like Clojure are going anywhere in the future.

  • dzonga a day ago

    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.

    • yogthos a day ago

      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.

      • pjmlp 13 hours ago

        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".

        • yogthos 8 hours ago

          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.

  • Kuyawa a day ago

    [dead]