I feel like everyone has some sort of justification for why their pet language is now the best because LLMs can work in it better for a bunch of reasons.
Javascript/Python is the best because there's so much code out there that the LLMs can train on, and LLMs can write lots of tests to make sure everything is correct. There's nothing to compile, so the LLM can iterate quickly.
Rust is the best because the LLM gets great feedback from the compiler because of its strong type system, and it can deal with the borrow checker for you.
Go is the best because it's a simpler language with a decent type system, and the LLM can reason about that well, and will never forget to check an `err` return. The compiler is fast, so the LLM can iterate quickly.
I could write similar praise for C, C++, Java...
At this point I don't think any language is the best "because LLMs". I think there are quite a few languages that LLMs are probably not good at, but you have lots of choices if you want something they are good at.
> Lisp programs are often much more concise because macros let you abstract away recurring patterns and make them part of the language itself
This is why Lisp never catches on. Each programmer invents their own ad-hoc, undocumented, barely working language in the form of those macros. The same thing happens in other languages with macros (like C and assembler).
I think half the article talks about why CL is good because it can resume from an exception, and half the article talks about why DSLs are good.
I think others have pointed out that most modern scripting languages can halt at exceptions without unwinding the stack. Python & Node both support this with core tooling.
As for DSLs, they constrain the LLM which generally helps with code quality. However why implement your DSL in the unconstrained chaos of CL? You can write DSLs in Rust which gives you static typing, a borrow checker, and clippy.
For LLMs, less code means fewer tokens, and tokens are what you pay for so you spend less on development.
I don't think that's strictly true.
What you need is for your LLM to be able to understand enough context to be able to make a change with as few token as possible, so if your code isn't expressive enough or if it has a tendrils calling lots of different functions/methods all over the place, then you'll have to give it much more code (context) than if you've got nice encapsulated modules that don't depend on other parts.
The design of your architecture (probably?) has a greater impact on token use in a large app than the language it's written in. Although, obviously, languages lend themselves to particular architectures so it's correlated.
I've had some of the same ideas, I would love a full macro system on a dependently typed language. My stab at it earlier in January was not quite the right thing, but I do think this is the way. Weirdly enough concision is even more important in LLM context than in regular human context.
I have similar experiences in Clojure. I use Pi and created an extension which teaches the LLM how to start a JVM with a Clojure nREPL listening in it. Added a tool which lets the agent evaluate any Clojure form inside the JVM. Sprinkled the setup with clj-reload and now the agent is using the nREPL as if it were its second nature.
What I like most is how fast testing goes: it modifies test code on disk, asks clj-reload to reload all affected namespaces, then reruns the tests. It's also fun to see how it verifies its assumptions by evaluating short programs through the nREPL.
I asked it to organize the various subsystems inside my playground repo into Integrant systems and make it possible for me to say things like "restart the http subsystem".
It also understands shadow-cljs: I replicated the necessary parts of the shadow CLI tooling in Clojure; now I can compile, watch and serve any number of CLJS apps located in various namespaces from inside the same JVM. There is no need to touch the command line any more: I just instruct the agent to start a particular CLJS app and it's there.
> because writing code used to be the slow part
I don't understand how people have that stated as a fact. Coding was never the slow part. Neither pre-llm, nor now. How it needs to be done is software engineering. And that corresponds now to the "thinking" part of llms, so unless you are making the llm "think in lisp" its not useful. How would that even work. training data to be completely in lisp ?
> Lisp programs are often much more concise because macros let you abstract away recurring patterns and make them part of the language itself
functions ?
> So the bigger the program gets, the bigger the difference. In my own experience the apps I've built in Common Lisp end up about six to seven times shorter than the Python versions
By that logic writing code in this concept language made up completely of symbols would take you even further ( https://github.com/artpar/guage ) but in practice it doesnt because llms arent trained to that extent on this.
Lisp has existed more than 50 years, more than most programming languages.
If it were a good programming language people would be using it more at this point.
AI needs a new Lisp Machine (like but not equal), the future computing principal part should be AI rather than human, env should be abstracted to AI.
I remember this guy back in the dotcom boom days, more than 25 years ago, who made an app that got acquired by Yahoo.
He claimed that Common Lisp was the best programming language for web apps, and that it gave him a massive advantage in creating his app.
What was his name again? Paul something? Oh yeah, Paul Graham.
Soon, hopefully, we will have evidence based analysis of those programming languages best suited for LLM authoring. Fwiw I doubt that CL will make the cut - but happy to be proven wrong. Obviously a large factor remains the facility of the human driver for a particular language.
Until then, I subscribe to the view that strong types fit LLM coding well since LLMs are prone to make silly mistakes when they patch together code examples in dynamic languages.
[Disclosure, my new language https://bil-lang.org aims to add “strong typing” around parallel programming to help weed out deadlock conditions.]
”Would you agree that some programming languages are better than others? If so then one of them must be the best.”
False. A partial ordering doesn’t guarantee a maximum element!
An ERP system in...LISP? None of the reasons given as to why that would be a good idea are really very convincing or specific to LISP?
The main things you want for ERP are just to simplify database interactions as far as possible and to give you as many and as customizable options as possible for data visualization and curating information for a non techie user. I dont really get why LISP?
Autolith is great with LLMs exactly because it's written in Common Lisp.
I use agents heavily on Common Lisp in some parts of production projects. Typically Codex on whatever is the current top model with vibe-patched Tron MCP. REPL-based agent development via MCP does feel faster but I haven't ever bothered to benchmark it.
A very big claim backed with poor arguments and easily disputed evidence.
This post reads like it was written by a Common Lisp fan who is looking for a reasons to say that Common Lisp is good for AI agents, rather than an AI agent user evaluating what languages are really best.
I've heard fans of both statically typed and dynamically typed languages advocate for their language. The static type fans say that the rigorous compilation process gives the LLM a fast iteration loop with clear messages from the compiler on what invariants aren't being upheld. The dynamically typed languages advocates talk about fewer tokens, the popularity of the language in the training data, and so forth. Guess what, these are the exact same arguments these communities made for human developers.
Personally, I don't know the answer. The industry has swung back and forth on this over the decades. Before AI code-gen static languages were on the upswing for a variety of reasons, including runtime efficiency and much better ergonomics thanks to modern type inference engines. I suspect those reasons are still valid, and also that statically typed languages give LLMs a leg up because it is easier to reason about them locally thanks to declared types and information hiding.
Are you saying this based on the fact that no-one will read or understand the code manually? That might be the case but on some areas, having a product understanding and knowing what to build, why to build matters a lot and sometimes the LLMs will write code that is not correct, doesn't make sense and they will continue down that path without explaining it.
I still believe that other languages which are understood by developers are and will be required and LLMs are trained on the same dataset so it can write the code.
It seems like an assumption here is that any language will be equally performant at runtime, for a given number of tokens burned to produce the code. I have never used any functional language for anything real (except maybe Mathematica). Is that true?
I am not an expert, just an engineer with years of experience. I switched to Rust a couple years ago. I was still learning before LLM generated Rust was good enough that I stopped coding by hand.
Again, not a language expert, but: if you can describe your domain or business logic as clearly as a strongly typed language with a rich type system, most of your issues are gone. Enum and Struct with all the other core types plus the match expressions does most of my mental heavy lifting. I do not even track any of the recent language changes.
What I really care about is the shape of what I am describing - does it translate to code? How much do I lose in the translation? I want to try other languages, particularly Lisp but Rust is at this moment my choice. I have my own UI framework (1), my own provenance based business domain generator and a few simple language parsers.
I am building apps where you can, for example, throw a CSV file (2), ask questions in English and get answers - without using an LLM. Parser. Rust is no doubt a great language to express - not as a programmer, but as a prompter. I do not write the code. I ask LLMs to generate it using only basic knowledge of Rust and its type system. This will be the key to work with LLMs for majority of people.
I keep bouncing the idea around of building a core in C or Rust then writing everything atop it using Janet. I love how readable lisps are (with macros, you can really move up the abstraction ladder quickly) and working on a live image should make iteration a breeze in an LLM.
I don't really agree with this. Having strong types and guardrails like in Haskell, Rust or OCaml helps _massively_ with LLMs because they get very clear messages back, and can express their logic using semantic types they can easily follow. Conversely, I've noticed that AIs (just like humans) tend to kind of lose the thread with very dynamic code
This is written by a person who never used LLMs.
LLMs need a language that:
- has opinions about how to write standard code
- has opinions about one way of formatting and codestyle
- has opinions about linting and integrated debugging
- has predictable strong types
- has opinions about integrated unit testing and a standard way to write them
- has an integrated toolchain
- has a strong stdlib and an upstreamed way to unify libraries
- (recommended) has a standard project layout _where_ to put its code (types, structs, helpers, utils, etc)
Go and Rust fit all these checkmarks except the last one. That's why those languages don't need kilometer long prompts to tell the LLM how to write code. Most of the prompting in those languages focuses around architecture and design, and not about style, tooling, or other artificially vague decisions.
Lisp is the most unopinionated language there is, therefore it is the worst in terms of lack of decisions encoded in its tooling.
And I'm not writing that as an opponent of the language, I've written scheme bindings for a couple of years in (academic) robotics.
The point that I am making here is that you _need_ an opinionated language for an LLM to make sense. Write linters and tools before code [1].
[1] https://cookie.engineer/weblog/articles/write-linters-and-to...
cant you do most of this with smalltalk too, or erlang?
I dont really understand what macros get you when llms exist since a llm doesnt really need to create dsls to get work done
Won’t you have to write entire stacks of code from scratch for lack of prior art in CL?
Seems to be written by somebody who has never worked within a team, never published a commercial piece of software (with the said team), and never used an LLM to write code. How is that possible? I love Common List and Racket. Love them to bits. I'd use them all day every day if it weren’t for that pesky LISP curse and the fact that nobody would want to work with me. LLMs, until recently were consistently forgetting parens, couldn't close functions properly. Somehow LLMs can't really count in their head, so it makes for a really... fun time with LISPs.
Lots of bad reasoning in this article.
So long as your feedback loop isn't slow enough to be taking you out of flow, it's fast enough. Having it be a few seconds vs a few hundred milliseconds mostly doesn't matter for a human, and will matter even less for an LLM.
On macros and DSLs, yes they're cool and even useful sometimes, but most of the software industry is working quite happily without them. And LLMs aren't going to change that because they are best when there's a lot of relevant patterns in their training data. That ends up being a far more important factor in their effectiveness than whether the language itself is token-efficient. It's much easier for an LLM to reason through how to do XYZ in Python where it already knows all the semantics and syntax than it is for it to do it in your DSL it's never seen before. To be clear, it can probably do both but will make mistakes an order of magnitude more in the DSL, and that's what will matter most for the LLM iteration time.
I recently wrote a comment on another thread that I think fits even better here:
In my circles I've noticed it's very easy for us to rationalize why our previous favorite language is also the perfect language for the agent era.
If your favorite language before was Python, why, LLMs are fluent in it! So much training data! So many libraries! Home of machine learning! None of that pesky compile time, agents don't need compile time safety anyway, they write such good test coverage! It's The Perfect Agentic Coding Language.
If it was Rust, by jove, an agent can easily handle the headache of satisfying the borrow checker, and now you get the best of all worlds! Safety! Near-C runtime performance! Abstractions! The only reason people didn't use Rust before was it was Too Hard and there were Too Many Furries and now it's not hard and you don't have to interact with them, so get on board. It's The Perfect Agentic Coding Language.
If it was Golang, oh my goodness, what a choice. Pretty fast compile time and pretty fast runtime. Agents get a tight feedback loop with build->run->test->edit. Not very complicated, code has to be written in a straightforward banging-rocks-together way. Good stable ecosystem! Rob Pike designed the language for people he said were "not capable of understanding a brilliant language but we want to use them to build good software." That's an arrogant, demeaning way to describe your colleagues but if they're LLM agents it's dead on! It's The Perfect Agentic Coding Language.
I could go on and on. I'm not immune either! My own favorite language is F# and when I feel like self-justifying, I play the same game:
It has access to the .NET ecosystem like C#, but I don't have to constantly remind the agents to prefer a style with immutable data and pure functions, they idiomatically do that in F#. Files have to be in order and can only refer to symbols defined "earlier" in order, if you want mutually-referential types or functions they have to be declared as such in a joint statement, so spaghetti is hard to create: each project's codebase naturally ends up in a layered bottom-to-top architecture. The language is terse enough to be token efficient, without being symbol soup. FSX scripts can be generated during agentic code reviews to demonstrate repros for discovered issues. If there's any type of code that still warrants me jumping in and writing some myself, that code would be data type definitions/domain modelling, and F# is a joy to write those in. It's The Perfect Agentic Coding Language.
Astronaut 1: So... now Lisp is the best programming language?
Astronaut 2: Always has been...
Zero visible experience with CL on top of a project list where half of the links give a 404. Others are unmaintained slop output. Sprinkled with Paul Graham references and the Harvard badge.
Sorry, I'm not impressed. How did that /run/ to the top of HN? [pun intended]
"Vorschusslorbeeren"? A clique of voters?
Boring.
I mean its cool but what about all of the extra infra I need to write because support for the lang is not as extensive and so more code I need to maintain?
don't think software companies will user change their software
That's a lot of power to mess things up that I wouldn't be putting into the hands of an LLM I don't trust.
In my experience, LLMs instantly find the reason for the crash and fix. They don't even need to go through the debugging phase anymore. It doesn't matter if you're generating c++ lisp or cobol.
In the benchmarks though here it is slow and consumes too much memory
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
But I find ideas like Carp very attractive.
Still common lisp is designed very good.
Lisp allows for some really, really complex and spaghetti code bases. I have seen the ultimate macro-hell from top to bottom. I know syntax does not matter, but i just cant honestly say i read lisp code as clear as something like Go. I guess it boils down to style. I have seen 100 lisp styles, and only one Go style.
> In Common Lisp your program won’t crash, it’ll stop and open a debugger with the whole stack and all the variables. You can just point your LLM at the debugger, and it’ll make its fix and resume the program.
> To my knowledge Common Lisp is the only mainstream language that does all of this.
Sounds like someone who has never used C# and Visual Studio? Even JavaScript is capable of doing this, honestly JavaScript might be the one language with the richest developer tooling of all time (possibly?), sad to say because there's nicer to work with languages out there.
Now as ever, there is no “best programming language”.
There’s the right tool for the job, there’s compliance with requirements, there’s personal preference.
Don’t let anyone ever tell you you are programming wrong.
Yeah... no. I don't think there is a best programming language, but I do think dynamically typed languages are worse for AI to code in compared to statically typed ones.
[dead]
"Would you agree that some programming languages are better than others? If so then one of them must be the best."
Unless of course there are multiple dimensions of "Good". I in my opinion this is exactly the case. There are best languages per dimension, but not absolutely best.
[dead]
Common Lisp isn't even a good programming language. There's nothing in CL that isn't in a ton of other languages now. When it was being designed it was way ahead, but now it's just way behind.
Maybe you could take CL as a foundation, introduce modern features and uniformity to the language, remove some of the insane complexity, tame the unhygienic macros, and come up with a pretty good language. Since about 7392 different flavors of scheme have tried to do this and mostly failed, I think this is very unlikely.
This is one of the most inane, fluff articles I’ve seen dumped in this site in a while. Nothing original, just a simplistic regurgitation of known stuff. Reads like lame, lazy LLM slop :(
Nah with llms the most used lang prolly has the best output
Lots of comments praising LLM's understanding of Common Lisp macros. I've seen them break badly at the macros-writing-macros level. I saw a current frontier model get so disoriented by one (a simple one!), it created something that expanded into a "(let (((".
(That's an impossible count (3) of parentheses on the RHS—like a six-fingered hand).