Hacker News new | ask | show | jobs
by gertlabs 13 days ago
The functional paradigm is a bit uncomfortable at first, but it does make problem solving feel... different. I personally find OOP to be the most intuitive for large scale systems design, but that's just me.

Most models do not perform particularly well in Clojure, but OpenAI models fully utilize the power of the language. Subjectively, it kind of seems to match the personality. Data at https://gertlabs.com/rankings?provider=openai

9 comments

> I personally find OOP to be the most intuitive for large scale systems design, but that's just me.

The beauty of Clojure shines through when you want to change something that cuts through a large part of a large project. If you are using mutable data, you may end up with many bugs from various pieces of code mutating objects inconsistently. With Clojure, if someone hands you data, you can't possibly break some distant piece of code by updating an object: it's just not possible because you only ever make fast, updated copies. The more complicated your codrbase gets, the more this benefit is realized.

I actually kind of think of it as an easier mechanism with similar outcomes to Rust's borrow checker. Only one piece of code ever owns the data so things end up much safer. However it is way easier to use IMHO because you just know that zero people own anything and everyone can read everything.

It also makes converting some code to be multi-threaded extremely easily and with some constraints guaranteeably correct.

Lots of dovetailing features neatly put together for both clarity and less bugs and more usable cores which are probably sitting idle.

> I personally find OOP to be the most intuitive for large scale systems design, but that's just me.

Once you're more comfortable with it and want to try a typed functional programming language, I highly recommend checking OCaml (or SML, if you're into old school tech) and see how the Module Functors are applied, most software will look extremely over-engineered after you write a few functors. It's the feature I miss the most when coding in F# or Gleam, for instance.

Raw models aren't as effective with clojure as they are with typescript or python, but clojure has a superpower that most other languages don't have: the REPL! Specifically nREPL and the ecosystem around it.

An LLM is only as good as its feedback loop. If your LLM can actually test the code it writes, it's going to be much more effective. Static types are a form of feedback (if it can use the LSP), unit/integration tests are another.

Clojure has an exceptionally good repl. LLMs can eval any piece of any function. They can test out functions they aren't familiar with. They can fetch data, try out different arguments, try different approaches before committing to one. They can query a database (read-only connection, of course), look at the result, fetch data from an API, and stitch it all together. It can even hook into your running program and debug it from the inside out!!

It makes it so much more effective at using libraries or paradigms that it isn't trained on. In my experience, hooking an LLM up to the clojure repl lets it write WAY more complex stuff. I'm talking like 10x more complex programs with zero errors, cause it can literally try it out every little piece before putting it together. It's like watching a human programming. But like, really fast.

Sorry I get a little ranty when clojure + LLMs come up, because I don't think most people realize what they're missing out on. It's crazy stuff. It's also easy peasy if you use vscode. There's an extension called calva-backseat-driver that just hooks it all up for you. Gives copilot access to the repl, and I think it exposes an mcp if you want to give claude access too.

GPT 5.4+ models are extremely good at writing Clojure, agreed. In the agentic coding part of our benchmark, they do have access to the REPL via bash if they choose to use it. Filtered here: https://gertlabs.com/rankings?mode=agentic_coding
Thanks for the link!

What would you say is missing from Clojure for large-scale OOP design? As I understand, Clojure gives you OOP a la carte. Objects (via maps/records/structs), polymorphic dispatch (via multimethods/protocols/case), types (via Malli/TypedClojure), inheritance (via derived, isa?, etc), some encapsulation (via defn-/^:private)...

Not the person you're replying to, but have you tried TypedClojure? I've always thought clojure-with-types would literally be the perfect language, but I also read TypedClojure is more of a research project than a real language that you should use in prod.
No sorry, of the things I've listed, I'd never seen nor heard of a project that uses Typed Clojure, nor probably inheritance via dervied/isa?.

For static (partial) typing, I instead use Malli schemas. I do this for every larger Clojure program I make, because there's always something that needs paranoia, or it's handy to generate example data.

I might just be a simpleton -- I never had the resolve to try an ambitious project in Clojure. I was not aware that you could get full OOP though, what you are describing feels like yes technically possible but kind of a hack to get inheritance / no type hierarchy enforcement. I'm no expert on the language though
I actually disagree. Once you remove the cruft and crap of the involved syntax, good OOP design tends to look damn close to FP design. So I flip your point of view - class based OOP is the hack - despite not really using Clojure or FP in my dayjob or hobby projects anymore. Most fun I had with OOP was definitely Common Lisp though.
Not sure if I'm reading this right, but the "success rate" table for OpenAI models shows Clojure near the bottom. And if I switch provider to Anthropic, success rate for most languages, including Clojure, goes up dramatically.
Success rate includes syntax/compilation failures as well as environment rule violations, and is almost entirely from one-shot code generations. Percentile shows how well the working submissions perform.

In long horizon agentic coding evaluations, strong models fix the syntax and percentile and it becomes a direct comparison of which submissions per language performed the best on average. You can filter for that here: https://gertlabs.com/rankings?provider=openai&mode=agentic_c...

> I personally find OOP to be the most intuitive for large scale systems design, but that's just me.

At one point, I was the same. But after going functional in Clojure, I can’t imagine going back. Using maps nd just having common functions that transform data into different data is definitely the way to go. This is with your time: https://youtu.be/aSEQfqNYNAc

It's fascinating that Clojure has consistently the best performing solutions and yet at the same time such a low success rate.

Do you have an idea as to why that is?

If I had to guess, two things lowering reliability:

A) Balancing parens might be tough on an LLM one-shot.

B) LLMs generate tokens sequentially, but s-expressions mean the first forms to be evaluated in a body are usually the last to be written, so the LLM has to sequentially generate layers of evaluation backwards.

First, we would need to agree on what "such a low success rate" means. Programmers have a thundering herd mentality: there are usually 2-3 "top things" that are in fashion at any given time and the herd tends to go towards these top things. They are not necessarily good or "successful" (however you define that term), they are just popular today.

From my point of view, Clojure is a very successful language. It has been in stable development for >10 years now, with no major breaking changes (!). I was able to start a business using it and now make a living from it, all of it possible largely because Clojure reduces incidental complexity so much.

Now, as to LLMs, I can see this discussion is mostly theoretical, so let me pitch in with data. I've been using LLMs for Clojure for a while now and it works fantastically, from what I read about other languages, quite a bit better for me than for others. Balancing parens was a problem for early LLMs without tools, Claude Opus with clojure-mcp tools doesn't encounter that problem at all.

Additionally, the ability to try things in the REPL means that LLMs are very effective: all hypotheses and solutions are immediately tested, with automatic feedback.

Overall I get great value from LLMs and I am able to solve large problems with them.

I've found it helps to give the model a lower nesting limit than you might give a human who has access to a paren-balancing editor. If all functions are shallow, there's less opportunity for paren balancing to get out of control, and reasoning about the evaluation flow doesn't have to jump back and forth so much.

This also doesn't hurt the code from a human reader's point of view.

If B), then maybe the LLM should be instructed to prefer things like the -> and ->> operators. So the first forms evaluated are also the first written.
Functional is far more comfortable to me. Trying to model all that state spread through out your program with no way to really isolate it or just reason about a small part of the program at a time, I find very stressful.
Rich Hickey's: Are We There Yet may be interesting to any one here: https://www.youtube.com/watch?v=ScEPu1cs4l0

I found this to be one of the more interesting talks I've watched.

Like you (I think) - I love functional languages.

But there's a problem I can't really figure out how to articulate where they reach a level where they stop "just working" imo. Maybe it's just me being too dumb.