Rendered at 22:51:47 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
gertlabs 49 minutes 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
gleenn 2 minutes ago [-]
> 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.
chamomeal 20 minutes ago [-]
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.
gertlabs 13 minutes ago [-]
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
xoxolian 33 minutes ago [-]
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)...
gertlabs 17 minutes ago [-]
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
chamomeal 16 minutes ago [-]
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.
andai 35 minutes ago [-]
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.
gertlabs 23 minutes ago [-]
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...
smitty1e 54 seconds ago [-]
"Lua: everything is a table
Tcl: everything is a string
Lisp: everything is a list"
Python: {"everything":"dictionary"}
pdimitar 34 minutes ago [-]
With respect, this topic in particular has been beaten to death.
I too liked Clojure when I tried it some years ago (agreed on the composition and data structures; both are _great_). But the real value-add is in the runtime, not the syntax. Java has a solid runtime but it's not yet as good as Erlang's, maybe even not up to the standards of Golang -- I am talking concurrency / parallelism here (for memory management I have no doubts Java is very good). And I know: green threads and stuff. Well, call me when you can do what Erlang / Golang can do. Then I'll look again, very seriously too.
Programming language syntax scarcely matters. It does to some extent but we the programmers tend to over-romanticize it. The runtime and its properties are the much better thing to optimize for.
chamomeal 14 minutes ago [-]
Are JVM virtual threads not on par with golangs's concurrency? I think core.async even uses virtual threads now
pdimitar 12 minutes ago [-]
If they are, I have not heard about it (which does not mean much, I check Java once a year). And if they really are then I'd give Java a serious look again because it's a mature ecosystem that was gimped by ancient runtime decisions for literal decades.
bcrosby95 33 minutes ago [-]
When it comes to concurrency, what can golang's runtime do that is so special? When I tried it, it seemed like a worse version of Erlang's for people that prefer C style syntax. Depending upon your design space pervasive immutability is a huge boon too and golang doesn't have that but Clojure does - Erlang obviously having that and more.
I always wished clojerl took off.
pdimitar 27 minutes ago [-]
I agree Golang is a worse version of OTP, no question about it, but if you are not allowed to code in Erlang/Elixir/Gleam (which sadly is 99.9% of the projects on the planet) then Golang is the next best thing.
It has footguns, sure, but with library support and discipline it can get you very far.
To me it's embarrassing that PLs still tout syntax and various other goodies, completely glossing over runtime. I might be missing something. But faux humble statements aside, I feel many others are the ones who miss something -- and that's the fact that doing stuff in parallel is a fact of life for 20+ years now and it's time all popular PL runtimes finally wake up to that fact.
If not, I am simply not considering them. And I am not saying that arrogantly though it sounds that way; there are some PLs that I _really_ liked and was almost heart-broken that I had to abandon them and not work professionally with them. But I have enough experience to know that runtime choice matters, a lot.
For the record, Racket was one of those PLs I abandoned. I know they started working on parallelism some years ago but I had to make a decision next week back then so, Elixir + Golang + Rust it is for me.
agambrahma 32 minutes ago [-]
Yeah, the content + feel felt like I'm reading this in 2013.
Nothing wrong with that, it's a good thing that stuff is discovered anew [as opposed to being lost/forgotten], but it did bring a smile to me.
meken 46 minutes ago [-]
> I do wish there were an easier way to move in the ]}]})))}-ness of block ends though.
I’m not quite sure what this means. How is it different/worse than all parens..?
fyi I use paredit and just hit ) and it moves me past any kind of paren/bracket. But even without that you can just hit left and right..?
HiPhish 48 minutes ago [-]
> I am now generating this website with Clojure
As everyone knows, you are not a true lisper until you have written your own static site generator.
It gave me such a great high with how easy it was to add my own "templating engine" on top, implemented all using macros. The downside is that the crash came hard; there is so much more to a good static site generator such as optimizing the output, supporting scoped CSS, server-side rendering of SPA framework components, and of course integration with the Node ecosystem (for better or for worse there is just so much useful stuff). I have since moved over to Astro. It's still fascinating how far I was able to push my own SSG all by myself though.
embedding-shape 32 minutes ago [-]
Heh, inspired by hiccup, I ended up implementing my favorite Clojure templating library but in Nix, exactly for the purpose of static site generation :) Even have a nifty demo of how it looks for that, it basically looks/works the same as hiccup: https://emsh.cat/niccup/examples/blog/
NetMageSCW 27 minutes ago [-]
I wonder if the author is familiar with Smalltalk - it has a very small syntax. In some ways so does Lisp, in other ways it has more than every other language, depending on what you think about operators versus functions.
BoingBoomTschak 34 minutes ago [-]
> The seq abstraction, for example, means I usually don’t have to worry about what kind of sequence I’m dealing with
Other than that, I agree, CL is baroque yet needs some hole filling here and there.
> Lisp: everything is a list
But that's wrong. Not even a little. Unless you mean LISP 1.5...
> Too much syntax
Funnily, I'm mostly okay with the new vector/set/hash-table literals, my big problem and that of some other people is the use of vectors in macros/special operators instead of lists. `(let [a b] ...)` instead of `(let (a b) ...)` is _not_ okay.
y1n0 28 minutes ago [-]
I haven’t used clojure in quite a while but what’s the issue with (let [a b] …)?
Is (let (a b) …) even valid clojure?
everforward 4 minutes ago [-]
I believe it would be (let ‘(a b)), but I’m not sure if that’s valid or not. That’s how Racket does its version of defn
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
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.
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.
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)...
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...
Tcl: everything is a string
Lisp: everything is a list"
Python: {"everything":"dictionary"}
I too liked Clojure when I tried it some years ago (agreed on the composition and data structures; both are _great_). But the real value-add is in the runtime, not the syntax. Java has a solid runtime but it's not yet as good as Erlang's, maybe even not up to the standards of Golang -- I am talking concurrency / parallelism here (for memory management I have no doubts Java is very good). And I know: green threads and stuff. Well, call me when you can do what Erlang / Golang can do. Then I'll look again, very seriously too.
Programming language syntax scarcely matters. It does to some extent but we the programmers tend to over-romanticize it. The runtime and its properties are the much better thing to optimize for.
I always wished clojerl took off.
It has footguns, sure, but with library support and discipline it can get you very far.
To me it's embarrassing that PLs still tout syntax and various other goodies, completely glossing over runtime. I might be missing something. But faux humble statements aside, I feel many others are the ones who miss something -- and that's the fact that doing stuff in parallel is a fact of life for 20+ years now and it's time all popular PL runtimes finally wake up to that fact.
If not, I am simply not considering them. And I am not saying that arrogantly though it sounds that way; there are some PLs that I _really_ liked and was almost heart-broken that I had to abandon them and not work professionally with them. But I have enough experience to know that runtime choice matters, a lot.
For the record, Racket was one of those PLs I abandoned. I know they started working on parallelism some years ago but I had to make a decision next week back then so, Elixir + Golang + Rust it is for me.
Nothing wrong with that, it's a good thing that stuff is discovered anew [as opposed to being lost/forgotten], but it did bring a smile to me.
I’m not quite sure what this means. How is it different/worse than all parens..?
fyi I use paredit and just hit ) and it moves me past any kind of paren/bracket. But even without that you can just hit left and right..?
As everyone knows, you are not a true lisper until you have written your own static site generator.
It gave me such a great high with how easy it was to add my own "templating engine" on top, implemented all using macros. The downside is that the crash came hard; there is so much more to a good static site generator such as optimizing the output, supporting scoped CSS, server-side rendering of SPA framework components, and of course integration with the Node ecosystem (for better or for worse there is just so much useful stuff). I have since moved over to Astro. It's still fascinating how far I was able to push my own SSG all by myself though.
Eh? That's completely lifted from CL (https://www.lispworks.com/documentation/HyperSpec/Body/t_seq...). Same for AREF/NTH, there's ELT.
Other than that, I agree, CL is baroque yet needs some hole filling here and there.
> Lisp: everything is a list
But that's wrong. Not even a little. Unless you mean LISP 1.5...
> Too much syntax
Funnily, I'm mostly okay with the new vector/set/hash-table literals, my big problem and that of some other people is the use of vectors in macros/special operators instead of lists. `(let [a b] ...)` instead of `(let (a b) ...)` is _not_ okay.
Is (let (a b) …) even valid clojure?