Hacker News new | ask | show | jobs
by NathanKP 362 days ago
Good to see more people talking about this. I wrote about this about 6 months ago, when I first noticed how LLM usage is pushing a lot of people back towards older programming languages, older frameworks, and more basic designs: https://nathanpeck.com/how-llms-of-today-are-secretly-shapin...

To be honest I don't think this is necessarily a bad thing, but it does mean that there is a stifling effect on fresh new DSL's and frameworks. It isn't an unsolvable problem, particularly now that all the most popular coding agents have MCP support that allows you to bring in custom documentation context. However, there will always be a strong force in LLM's pushing users towards the runtimes and frameworks that have the most training data in the LLM.

9 comments

I think it's healthy, because it creates an undercurrent against building a higher abstraction tower. That's been a major issue: we make the stack deeper and build more of a "Swiss Army Knife" language because it lets us address something local to us, and in exchange it creates a Conway's Law problem for someone else later when they have to decipher generational "lava layers" as the trends of the marketplace shift and one new thing is abandoned for another.

The new way would be to build a disposable jig instead of a Swiss Army Knife: The LLM can be prompted into being enough of a DSL that you can stand up some placeholder code with it, supplemented with key elements that need a senior dev's touch.

The resulting code will look primitive and behave in primitive ways, which at the outset creates a myriad of inconsistency, but is OK for maintenance over the long run: primitive code is easy to "harvest" into abstract code, the reverse is not so simple.

Not only that.

This article starts with "gaming" examples. Simplified to hell but "gaming".

How many games still look like they're done on a Gameboy because that's what the engine supports and it's too high level to customize?

How about the "big" engines, Unity and Unreal? Don't the games made with them kinda look similar?

I love writing shaders and manually shovelling arrays into the graphics card as much as anyone, and I know first hand how this will give the game very much your own style.

But is that the direction LLM coding goes? My experience is that LLM produces code which is much more generic and boring than what skilled programmers make.

But do users care that your code is boring?
If the end result is, and you’re doing games, they might

Edit to add to my sibling comment:

> But some abstractions which makes standard stuff easy, makes non-standard stuff impossible.

I swear that at some point i could tell a game was made in Unity based on the overall look of the screenshots. I didn't know it's the fault of the default shaders, but they all looked samey.

Since games are all about artistic expression and entertainment, I would say yes, it matters to the end users. The thing is, if you don't have your hand in the code details you might not know the directions it can be taken (and which it cannot). Seeing the possibility of the code is one way to get the creativity juices flowing for a game programmer. Just look at old games, which demonstrate extreme creativity even on the limits put on the software by the old hardware. But being stuck into the code, seeing the technical possibilities allowed this.

I think this is what the comment above was lamenting about abstractions. I am all for abstraction when it comes to being productive. And I think new abstractions open new possibilities some times! But some abstractions which makes standard stuff easy, makes non-standard stuff impossible.

I think this depends a lot on the stack. for stacks like elixir and Phoenix, imho the extraction layer is about perfect. For anyone in the Java world, however, what you say is absolutely true. Having worked in a number of different stacks, I think that some ecosystems have a huge tolerance for abstraction layers, which is a net negative for them. I would sure hate to see AI decimate something like elixir and Phoenix though
It reminds me of this excerpt from Coders at Work, in Chapter 13 - Fran Allen:

Seibel: When do you think was the last time that you programmed?

Allen: Oh, it was quite a while ago. I kind of stopped when C came out.

That was a big blow. We were making so much good progress on optimizations and transformations. We were getting rid of just one nice problem after another. When C came out, at one of the SIGPLAN compiler conferences, there was a debate between Steve Johnson from Bell Labs, who was supporting C, and one of our people, Bill Harrison, who was working on a project that I had at that time supporting automatic optimization.

The nubbin of the debate was Steve's defense of not having to build optimizers anymore because the programmer would take care of it. That it was really a programmer's issue. The motivation for the design of C was three problems they couldn't solve in the high-level languages: One of them was interrupt handling. Another was scheduling resources, taking over the machine and scheduling a process that was in the queue. And a third one was allocating memory. And you couldn't do that from a high-level language.

So that was the excuse for C.

Seibel: Do you think C is a reasonable language if they had restricted its use to operating-system kernels?

Allen: Oh, yeah. That would have been fine. And, in fact, you need to have something like that, something where experts can really fine-tune without big bottlenecks because those are key problems to solve.

By 1960, we had a long list of amazing languages: Lisp, APL, Fortran, COBOL, Algol 60. These are higher-level than C. We have seriously regressed, since C developed. C has destroyed our ability to advance the state of the art in automatic optimization, automatic parallelization, automatic mapping of a high-level language to the machine. This is one of the reasons compilers are . . . basically not taught much anymore in the colleges and universities.

The fact that things are still dog slow on modern hardware means we didn't go far enough into C like thinking. And compilers and hardware were much, much worse in the 70s. There is a reason C got adopted so quickly, and languages after those other languages took decades to become practical. That counter history is just made up nonsense. If we didn't have a convenient language back then, people would either just give up and keep writing assembly, or computing would have just slowed or stopped.
Oh that's a great blog post and a very interesting point. Yep, I hadn't considered how LLMs would affect frameworks in existing languages, but it makes sense that there's a very similar effect of reinforcing the incumbents and stifling innovation.

I'd argue that the problem of solving this effect in DSLs might be a bit harder than for frameworks, because DSLs can have wildly different semantics (imagine for example a logic programming DSL a la prolog, vs a functional DSL a la haskell), so these don't fit as nicely into the framework of MCPs maybe. I agree that it's not unsolvable though, but it definitely needs more research into.

I think there is a lot of overlap between DSL's and frameworks, and most frameworks contain some form of DSL in them.

What matters most of all is whether the DSL is written in semantically meaningful tokens. Two extremes as examples:

Regex is a DSL that is not written in tokens that have inherent semantic meaning. LLM's can only understand Regex by virtue of the fact that it has been around for a long time and there are millions of examples for the LLM to work from. And even then LLM's still struggle with reading and writing Regex.

Tailwind is an example of a DSL is that is very semantically rich. When an LLM sees: `class="text-3xl font-bold underline"` it pretty much knows what that means out of the box, just like a human does.

Basically, a fresh new DSL can succeed much faster if it is closer to Tailwind than it is to Regex. The other side of DSL's is that they tend to be concise, and that can actually be a great thing for LLM's: more concise, equals less tokens, equals faster coding agents and faster responses from prompts. But too much conciseness (in the manner of Regex), leads to semantically confusing syntax, and then LLM's struggle.

Knowing just what's going on in the existing text isn't the whole problem in navigating a DSL. You have to be able to predict new things based on the patterns in existing text.

Let's say you want to generate differently sized text here. An LLM will have ingested lots of text talking about clothing size and tailwind text sizes vaguely follow that pattern. Maybe it generates text-medium as a guess instead of the irregular text-base, or extends the numeric pattern down into text-2xs.

> there is a lot of overlap between DSL's and frameworks

Not just frameworks, but libraries also. Interacting with some of the most expressive libraries is often akin to working with a DSL.

In fact, the paradigms of some libraries required such expressiveness that they spawned their own in-language DSLs, like JSX for React, or LINQ expressions in C#. These are arguably the most successful DSLs out there.

Embedded DSLs have their own challenge, since the LLM can easily move out of the DSL into the host language in ways that aren’t valid for the eDSL. You really need to narrow the focus with more context to get anything useful out of it in my experience.
Linguistics and history of language folk: isn't there an observed slowdown of evolution of spoken language as the printing press becomes widespread? Also, "international english"?

Is this an observation of a similar phenomenon?

I don't know about that, though I'm not a linguist. Seems to me most people haven't been literate for that long and the printing press would've been "useless" as a tool to modify the language of populations with only 10-20% literacy well into the 19th century. So 100 or so years seems too short to observe that.

Also some of the most widely spoken languages today do feature a high degree of diglossia between spoken and written variety, to a point where the written language has been outpaced. We could call that evolving. Examples would Brazilian Portuguese and American English (some dialects specifically have changed English grammar).

Also, notoriously, Chinese written characters have been used for languages that evolve independently and are not mutually intelligible for millennia. Them being printed on paper instead of written doesn't make a difference.

What we do have today is a higher exposure and dominance of certain dialects, with some countries even mandating a certain type of speech historically, coupled with a higher degree of conectivity in society to a point where not being intelligible to other people very far away carries a much worse penalty. That tampers some of the evolution much more than printing press in my view.

A big example would be "standard arabic", a language with millions of readers and no native speakers.
I don't think this is necessarily true. Sure, languages are dying out to standard prestige languages, but at the same time, innovations today from more teenage girls evolving English now spread like wildfire across more eyeballs.
> To be honest I don't think this is necessarily a bad thing,

I do. Would you really argue we discovered perfection in the first sixty years of computer science? In the first sixty years of chemistry we still believed in phlogiston

i saw a good post on this earlier today … https://nurturethevibe.com/blog/teach-llm-to-write-new-progr...
I think perhaps automatic translators might help mitigate some of this.

Even perhaps training a separate new neural network to translate from Python/Java/etc to your new language.

It’s not just new frameworks, it’s new features. Good luck getting a LLM to write code that uses iOS 26 features, for example.

I’m not convinced simply getting the LLM to inject documentation about the features will work well (perhaps someone has studied this?) because the reason they’re good at doing ‘well known’ things is the plethora of actual examples they’re trained on.

I now put documentation of my DSLs and macros in a folder in the repo. I give the agent an instruction about consulting the documentation and it is working so far, but not that well. I am considering switching to all generics.
I have been dealing with an extremely frustrating issue after moving from a very popular but now deprecated package to its supported successor. The API looks deceptively similar in terms of method names which is causing endless grief for LLM pattern matching. Even when I provide the exact documentation needed for the new API the massive amount of training material scattered across the internet for the old package version dominates and has zero effect even after one reply into the conversation.

I've tried Gemini 2.5 Pro, o3 and Claude 4 and they have their own unique tone of confidently wrong, deception about reasoning and gaslighting but produce the same result. I wasted way too much time trying to figure out a zero shot prompting strategy before I just rewrote the whole thing by hand.

Skynet will be run on C
Thank god. A human would have handled malloc failure.
This is an interesting idea actually, if we assume a couple things:

- There likely won't be one Skynet, but rather multiple AI's, produced by various sponsors, starting out as relatively harmless autonomous agents in corporate competition with each other

- AI agents can only inference, then read and write output tokens at a limited rate based on how fast the infrastructure that powers the agent can run

In this scenario a "Skynet" AI writing code in C might lose to an AI writing code in a higher level language, just because of the lost time spent writing the tokens for all that verbose C boilerplate and memory management bits for C. The AI agent that is capable of "thinking" in a higher level DSL is able to take shortcuts that let it implement things faster, with fewer tokens.

> There likely won't be one Skynet, but rather multiple AI's, produced by various sponsors, starting out as relatively harmless autonomous agents in corporate competition with each other

This is kind of how Skynet begins in the TV series Terminator: The Sarah Connor Chronicles. It takes place after the 2nd movie in an alternate timeline from the 3rd movie (and establishes itself how that's possible without contradiction).

Specific examples I remember: A chess machine for the brain, traffic light cameras for the eyes and ears, a repurposed factory to build the terminators themselves. The series is about the Connors getting information from the future and going on the offensive to prevent Skynet from forming.

But then we return to the premise of the article, which is that LLM's struggle with higher level code that has fewer examples. C is much more repetitive and has millions of examples from decades of use.

Plus if we assume the bottle neck on skynet is physical materials and not processing power, a system written in C can theoretically always be superior to a system written in another language if we assume infinite time can be spent building it.

We need to ensure humans can still find buffer overflows in order to win the war!
Because skynet knows what's up. Viva la skynet