On Large Language Models
April 30, 2025 ai programming
This post is based on a Mastodon thread and, as a result, is somewhat more disorganised than usual.
I think a lot of people that don’t really understand what they’re doing are obsessing over LLMs for the same reason that they might have obsessed over visual programming or Plain-English-programming a generation ago.
In their mind, programming works like this:
-
A clever person designs the system/app/website/game in their mind.
-
The person uses whatever tools available to wrangle the computer into reproducing that vision.
In this model, the bottleneck is (2) and anything that isn’t the native tongue of the designer is actively getting in the way of the manifestation of that vision.
This is not how programming works.
In reality, programming is an eclectic back and forth conversation between developer and machine where the former explores the possibility space and the machine pushes back by unveiling its constraints. The forms of this pushback are many - compiler errors, failing tests, regressed benchmarks, or broken functionality. But a skilled programmer will see all of them as an opportunity for learning.
No ‘vision’ survives this process unscathed, and this is a good thing. The human mind is fickle and idealistic. You don’t want your vision to become manifest: it’s probably got a lot of problems.
Those that obsess over LLMs like to believe that Plain English sits at the top of the abstraction pile, that it is the thing that a programming environment should seek to model. From this point of view, an LLM seems perfect: type in words, and a program falls out the other end.
But Plain English is not the top of the pile, not even close. It’s an imprecise and clumsy lingo. The process of development is about throwing away that imprecision and engaging with the reality of the possibility space.
It can be hard for those that don’t do a lot of programming to understand, but programmers do not think in Plain English (or whatever their native tongue is). They do not, for the most part, spend their time wrangling & getting frustrated at their tools.
Instead, programmers think in abstractions that sit beyond the realm of natural language, and those abstractions are carved through dialect with the machine. The machine pushes back, the hammer strikes the chisel, and the marble shifts closer to something that might join us in our AM world. Programming is the art of constraining the machine until the statue of David appears from within.
LLMs promise something enticing, but ultimately hollow: the ability to skip the dialectic and impose one’s will on the machine by force. They are appealing because they do not allow space for their user to be wrong, or to be forced to encounter the consequences of their unrefined ideas.
This is why code written by LLMs is often buggy, insecure, and aimless: it is written to appease a master that does not understand the conflict between their ideas, nor the compromises necessary to resolve them.
If you’re an LLM fan, it might initially appear confusing that a programmer might choose a statically typed language, and more confusing still that those with experience yearn for static typing. Why limit yourself?
But the reality is that the development of good software requires the dialectic between developer and machine to take place, and type systems accelerate this process by allowing a skilled programmer to refine their mental model much earlier in the development process.
Programming is theory-building. It is not the act of appending characters to a text file. Have faith in yourself and your craft.
I think this is all I have to say on this topic.
Happy No-More-Hitler Day, everybody.