Skip to content

CONCEPT Cited by 1 source

Language extension vs replacement

Language extension vs replacement is the design question that shows up whenever an entrenched programming or query language has well-known design problems but its ecosystem (users, tools, drivers, training material, integrations, existing code) is too large to walk away from.

The two failure modes:

  1. Replace it. Design a new language that fixes the problems. For any language of real size this has failed repeatedly — the new language starts with zero adoption, and the entrenched language's ecosystem (the part users care about) doesn't come along until the replacement reaches some critical mass of users + tools + drivers + IDE integration. It never does.
  2. Accept the pain and don't change it. The cheap default. Users keep hitting the design problems; the language's perceived learnability / readability / composability deficit compounds.

The third option — and the one the 2024-08-24 GoogleSQL pipe-syntax paper is a canonical production instance of — is to extend the entrenched language in place. Add new surface syntax that:

  • sits alongside the old syntax, not instead of it, so every existing query / program / tool / driver / training doc keeps working;
  • is additive and optional, so adoption is query-by-query or file-by-file with no migration project;
  • compiles down to the existing evaluation model / runtime / planner, so no new engine is needed to run the extended code.

GoogleSQL's pipe operator |> is the textbook realization for SQL (see patterns/pipe-syntax-query-language for the specific query- language shape). The paper's own framing of the problem is the canonical wiki statement:

"New language adoption is a significant obstacle for users, and none of the potential replacements have been successful enough to displace SQL." — GoogleSQL paper, 2024-08-24 (Source: sources/2024-08-24-google-pipe-syntax-in-sql)

Why extension tends to beat replacement

  • Ecosystem > language merit as an adoption force. A worse language with a larger ecosystem wins adoption against a better language with a smaller one.
  • Additive extensions inherit the ecosystem for free. All existing tooling still parses the extended language (additions don't break anything the parser already accepts). Drivers, ORMs, BI dashboards, ETL pipelines, training material keep working unchanged.
  • Zero migration cost. Users adopt the new feature locally where it helps; everywhere else nothing changes. There is no rollout campaign, no flag day, no migration plan.
  • One planner / runtime. The new syntax compiles down to the same evaluation model the engine already runs. No dual execution paths, no new optimizer, no new type system.

When replacement is the right answer anyway

Extension isn't always viable. Replacement becomes the right choice when:

  • The design problem is in the semantics, not the syntax. New syntax wraps the same evaluation model — if the evaluation model itself is wrong (concurrency model, memory model, consistency model, effect system), extension can't reach it.
  • The language has no extension point. Some grammars are hostile to additive features — any new syntax breaks backward compat — in which case a parallel language with an interop bridge is the honest move.
  • The ecosystem is small enough to port. If the entrenched language only has a few thousand users and limited tooling, a successor with a transpiler or interop layer can credibly replace it.

TypeScript extending JavaScript, C++ starting as "C with classes", and GoogleSQL extending SQL sit on the extension side of the line. ReasonML → Reason → ReScript illustrates the unstable-equilibrium case — a parallel language with a JS interop bridge, still fighting the ecosystem gravity of TypeScript.

Structural preconditions for extension

  • The entrenched language has a parse surface that tolerates additions. SQL's token-based grammar lets a new infix operator like |> slot in without conflicting with existing productions. A grammar with a lot of ambiguity resolution rules would not.
  • The evaluation model already covers the new feature's semantics. Pipe syntax in SQL is "just" relational algebra in a different order — the planner already does this reordering internally, so surfacing it is a parser + desugaring change, not a new operator.
  • One authoritative spec. If the language has many uncoordinated dialect owners (the SQL standard is notionally this, but GoogleSQL, T-SQL, PL/SQL, etc. all drift), an extension propagates at dialect-level only. GoogleSQL's shared-dialect-across-engines property (see systems/googlesql) is exactly the lever that lets one grammar change ship across BigQuery + F1 + Spanner.
  • concepts/backward-compatibility — additive extensions preserve backward compat by construction; this is the property that makes extension possible.
  • patterns/gradual-transpiler-migration — the replacement-side pattern when you do need a successor language: bridge old and new via a transpiler, shift source of truth in phases. Figma's Skew → TypeScript migration is the wiki's canonical instance.
  • concepts/tight-migration-scope — the analogous concept at the substrate level: swap one axis (language, compute platform, storage engine) while preserving every other abstraction.

Seen in

  • sources/2024-08-24-google-pipe-syntax-in-sql — Google Research paper explicitly articulating the design stance: SQL has real problems, new-language replacements have repeatedly failed to achieve adoption, the productive move is to extend SQL from within. Pipe syntax (|>) as the concrete extension.
Last updated · 200 distilled / 1,178 read