DEV Community

Cover image for A 'perfectible' language: why the idea is beautiful and why it'll fail anyway
Juan Torchia
Juan Torchia

Posted on • Originally published at juanchi.dev

A 'perfectible' language: why the idea is beautiful and why it'll fail anyway

Why aren't the best programming languages the most used ones? We've been asking this for decades and the uncomfortable answer hasn't changed: because technical quality was never the deciding factor. Never was. And yet, every time a new language design proposal shows up, the debate zeroes in on syntax, type systems, ergonomics. As if that were the actual problem.

I read the HN post about a language designed to be "perfectible" — a system where syntax can evolve in a controlled way, where the language can correct its own design mistakes without breaking backwards compatibility. I thought the idea was beautiful. Genuinely. Then I sat there for ten minutes thinking about everything that isn't going to work.

This is the most pessimistic post I'm going to write this month.

Programming language design, syntax evolution, and the technical merit trap

The argument for "perfectible" languages starts from a correct diagnosis: every mature language accumulates design debt. Python has the GIL. JavaScript has this. C++ has... well, C++. And once those decisions are in production, changing them is nearly impossible because there are millions of lines of code depending on that broken behavior.

The proposed solution is elegant on paper: you design the language from day zero with evolution mechanisms built in. Every feature has an explicit lifecycle. You can deprecate syntax, introduce new forms, and the tooling helps you migrate. The language can learn from its own mistakes.

It's exactly the kind of idea that generates 400 comments on Hacker News and zero real adoption five years later.

I'm not saying that out of cynicism. I'm saying it because I lived it three times.

The three languages I loved that the ecosystem abandoned

CoffeeScript, 2012. I was 21, studying Computer Science at UBA during the day and working nights, and CoffeeScript felt like the obvious answer to everything horrible about JavaScript. Clean syntax, arrow functions before they existed, classes that actually made sense. I shipped production code in CoffeeScript. It was genuinely prettier.

Then ES6 arrived. And Babel. And the entire ecosystem migrated in 18 months. Not because CoffeeScript was bad — but because big companies bet on ES6, because IDEs adopted it, because hiring managers started asking for "modern JavaScript." CoffeeScript didn't lose on technical merit. It lost because it was playing alone.

Elixir, 2018. I fell in love with Elixir in a week. Concurrency as a first-class citizen, real pattern matching, lightweight processes, fault tolerance by design. I built a couple of internal services. I evangelized inside the team. It was the language that solved exactly the problems I had.

I abandoned it in 2020 not because Elixir got worse. I abandoned it because when I needed to add people to the team, the pool of candidates with Elixir experience in Argentina was microscopic. Every time I needed help with a weird problem, the community response time was 10x what I'd get on Stack Overflow for Python. The language was better. The ecosystem wasn't.

Nim, 2021. I've talked about this one less. Nim has one of the most technically interesting proposals I've ever seen: compiles to C, powerful metaprogramming, pythonic syntax, systems-language performance. I studied it seriously during the pandemic, when I was making my pivot into software development full-time.

Nim exists. Nim has users. Nim is still in active development. But if you had to choose today between Nim and Go for a new project, the decision wouldn't be technical — it would be about who uses it, what companies back it, how many packages exist, whether your next employer has ever heard of it.

# This Nim code I wrote in 2021 is still one of my favorites
# A simple HTTP server with expressive types
import asynchttpserver, asyncdispatch, json

# Nim's type system let you do this elegantly
type
  ApiResponse = object
    status: string
    data: JsonNode
    timestamp: int64

proc handleRequest(req: Request): Future[void] {.async.} =
  # Real pattern matching, without the boilerplate of other languages
  case req.url.path
  of "/health":
    let resp = ApiResponse(
      status: "ok",
      data: newJNull(),
      timestamp: getTime().toUnix()
    )
    await req.respond(Http200, $(%resp))
  else:
    await req.respond(Http404, "not found")
Enter fullscreen mode Exit fullscreen mode

This code never made it to production. Not because it didn't work. Because the CTO asked "who else in the market uses this?" and the honest answer was "not many."

Why a 'perfectible' language faces the exact same problem

A language with controlled syntax evolution has a bootstrap problem that good design ideas don't solve.

For the evolution mechanism to be valuable, you need an existing codebase that needs to evolve. To have that codebase, you need adoption. To have adoption, you need mature tooling, packages, IDEs, courses, companies that hire for it. All of that takes years and requires someone to bet real resources.

That's the same trap CoffeeScript fell into, Elixir for conservative companies, and Nim. It's not a technical quality trap. It's a coordination trap.

I looked at how AI agent benchmarks are being gamed and thought something similar: technical rankings measure what's measurable, not what matters in production. A language can win every ergonomics and design benchmark and still be irrelevant in five years.

I also thought about the debate around contributing to the Linux kernel with AI. Linux carries 30 years of accumulated inertia. C has 50. They're not the best possible languages for what they do — they're the languages that won the early adoption war and now have moats so deep that no technical superiority crosses them.

The mistakes every new language designer makes

Mistake 1: Believing the problem is technical. Programming language design is a social network problem as much as a computer science problem. The language big companies adopt becomes the standard. The one that doesn't get them stays in permanent niche.

Mistake 2: Underestimating the cost of migration. Even a language with perfect evolution mechanisms requires devs to learn those mechanisms, tooling to support them, code reviews to incorporate new semantics. Cognitive energy has limits. When TypeScript competes with "learn X's evolutionary type system," TypeScript wins by default.

Mistake 3: Confusing early adopter community with real traction. The first 500 users of any interesting language are enthusiasts who write compilers as a hobby. That predicts nothing about corporate adoption. And without corporate adoption, there are no serious third-party packages, no hiring market, no future.

Mistake 4: Not having a company backing it. Rust has Mozilla and now the Rust Foundation. Go has Google. Kotlin has JetBrains. Swift has Apple. TypeScript has Microsoft. What does your perfectible language have? If the answer is "a passionate community," I already know how the story ends.

// Meanwhile, this is what I run in production in 2026
// TypeScript: not the best possible language, but the one that won
interface LanguageEvolution {
  technicalMerit: number;      // What designers optimize for
  corporateAdoption: number;   // What actually determines the outcome
  matureTooling: boolean;      // The factor nobody mentions in HN posts
  companyBacking: string | null; // null === existential risk
}

// The function no "language of the future" post wants to write
function survivalPrediction(lang: LanguageEvolution): string {
  if (!lang.companyBacking && lang.corporateAdoption < 0.3) {
    return "eternal niche or silent death"; // CoffeeScript, Nim, Elm...
  }
  if (lang.matureTooling && lang.companyBacking) {
    return "has a real shot"; // Rust, Go, Kotlin
  }
  return "depends on whether someone big bets on it"; // The limbo
}
Enter fullscreen mode Exit fullscreen mode

This connects to something I wrote about security in code reviews: the most interesting technical problems are rarely the ones that determine which technology survives. What survives is what has enough organizational inertia that abandoning it costs more than tolerating it.

The part that breaks my heart

There's something genuinely sad here that I want to be honest about.

The idea of a language that can correct its own design mistakes is a real answer to a real problem. Python 3 took over a decade to replace Python 2 — and that was with Guido van Rossum, the PSF, and Google putting resources in. Imagine making that transition without that infrastructure.

When I saw the post about the dancer with ALS controlling a live performance with brainwaves, I thought about the distance between what's technically possible and what actually becomes ubiquitous. BCI technology has existed for decades. The live implementation I watched was beautiful. But between that and mainstream adoption there's an abyss that technical quality alone doesn't cross.

Languages are the same. Deadlocks in Rust are a real problem that Rust solves with remarkable technical elegance. But Rust took 10 years to get into the Linux kernel, and that was with Mozilla and the Rust Foundation pushing hard. An indie language with better ideas doesn't have those 10 years or that backing.

A beautiful idea without adoption is philosophy. And philosophy doesn't run in production.

FAQ: Programming language design and syntax evolution

Why don't technically superior programming languages always win?
Because language adoption depends more on network effects than technical merit. A language with worse design but more available packages, more devs in the job market, and better IDE support is more attractive in practice than a technically superior one with a small ecosystem. COBOL still runs critical banking systems not because it's the best language but because the cost of migrating exceeds any technical benefit.

What does it mean for a language to be 'perfectible' or have controlled syntax evolution?
It's a design where the language includes explicit mechanisms to deprecate features, introduce new syntax gradually, and migrate existing code in an assisted way. The idea is to avoid the Python 2→3 problem: being able to improve the language without breaking compatibility or requiring massive manual migrations. Technically interesting, but it requires existing code to migrate — which requires prior adoption.

Are there examples of languages that successfully evolved their syntax?
JavaScript is the most notorious case: ES6, ES7, and later versions introduced radical changes (arrow functions, async/await, modules) without breaking old code, thanks to Babel and transpilation. But JavaScript pulled that off because it already had massive adoption before it started evolving. Python also evolved, but the 2→3 transition took 12 years and had enormous friction. Rust introduces changes through editions (Rust 2018, Rust 2021) — that's probably the model closest to what's being proposed.

Why do so many promising programming languages fail?
The bootstrap problem: you need an ecosystem to get adoption, and you need adoption to get an ecosystem. Languages that break that cycle usually do it because a large company adopts them internally (Go at Google, Kotlin at JetBrains/Android, Swift at Apple) or because they solve a problem so specific and urgent that the community builds the ecosystem from the ground up (Rust for GC-free systems at Mozilla). Without one of those two paths, the language stays in permanent niche.

Does it make sense to learn a programming language that isn't mainstream?
Yes, but with clear expectations. Learning Elixir, Haskell, Nim, or any niche language makes you a better programmer — it exposes you to paradigms and solutions you later apply in any language. The problem is building a product or service that depends on that language for a company: the risk of not finding devs, packages going unmaintained, or the language stopping evolution is real and needs to be weighed carefully.

What's the most underrated factor in a programming language's success?
Day-one tooling. Not the tooling when the language matures — the tooling available when a dev tries it for the first time. If autocomplete doesn't work well in VS Code, if the debugger is a pain, if a formatter doesn't exist, the dev discards it that first afternoon and never comes back. Rust invested heavily in rust-analyzer and cargo very early. Go had gofmt from the start. That's not accidental — designers who understand that a language competes for developer attention prioritize tooling over language features.

What I actually think

I want this perfectible language to succeed. Genuinely. The idea of correcting design mistakes in production is one of the most honest responses to the problem of technical debt in mature languages.

But I'm empirical, not romantic. The numbers don't lie: of all the languages with interesting technical proposals that show up on HN every year, less than 1% reach significant corporate adoption within ten years. Not for lack of good ideas. For lack of the specific combination of institutional backing, market timing, and early tooling that turns an experiment into infrastructure.

What worries me most about the "perfectible languages" discourse is that it assumes the core problem is technical. That if you design the evolution mechanism well enough, the language will be able to adapt and survive. But evolution doesn't save you if you don't have critical mass to start evolving in the first place.

I keep writing TypeScript. Not because it's the best possible language. Because it has the ecosystem I need, because my team knows it, because candidates list it on their CVs, because Railway supports it first-class, because it has 15 years of answers stacked on Stack Overflow.

And that, more than any design elegance, is what determines what runs in production at 3am when something breaks.

Do you have your own favorite language that never went anywhere? I want to know which one and why you think it didn't catch on. Write to me.

Top comments (0)