Skip to content
beskid The Beskid Book

Beskid

Jump to a Beskid service

Beskid

Jump to a Beskid service

1.6 Are we really standing on the shoulders of giants?

From assembly to VMs, how abstraction stacked up and which traps language designers keep stepping in.

Are we really standing on the shoulders of giants?

We tell ourselves each generation stands on the shoulders of giants. In practice we often stand on a pile of runtimes and call it progress.

Climbing a stack of runtimes

A compressed history of “getting further from the machine”

Section titled “A compressed history of “getting further from the machine””
timeline
  accTitle: From assembly to low-code
  accDescr: Stages of moving further from the machine, from assembly through native languages and managed runtimes to frameworks and low-code.
  title Getting further from the machine
  section Machine level
    Assembly : you are the machine (sort of)
    Macros : copy-paste with consequences
  section Native languages
    C : portable enough, segfaults included
    C++ : C with extra steps and a standards committee
  section Managed runtimes
    Managed VMs : write once, run anywhere (terms and conditions apply)
    JIT : optimize what you actually ran, eventually
  section Intent first
    High-level : express intent, pray the runtime agrees
    Frameworks : express intent in the framework's dialect
    Low-code : express intent with buggy, react-flow bootstrapped nodes

Each step traded control for reach:

  • Assembly gave truth and pain.
  • C gave portability and manual memory.
  • Java / .NET pushed toward virtual machines so hardware details could be ignored, until they could not (GC pauses, container memory, AOT revivals).
  • JIT promised peak performance without ahead-of-time commitment; you paid in warmup, complexity, and “works on my machine” bytecode.

The run anywhere dream was real enough to reshape hiring. It also abstracted languages into runtimes until the runtime became the real product (CLR, JVM), and the language became syntax for feeding it.

Traps of the human mind when designing languages and frameworks

Section titled “Traps of the human mind when designing languages and frameworks”

“We survived C++ enterprise projects” becomes “C++ is fine for everything.” The failures are in postmortems, not conference stages.

“If Rust is hard, hard must mean good.” Sometimes hard means your tool is fighting your actual workload.

Shrug: false equivalence

Designers add escape hatches until the language is three languages in a trench coat. Compassion for power users becomes tax for everyone else.

“If you are not using X, you are doing it wrong.” X changes every eighteen months. Moral certainty does not.

When the VM is the platform, language innovation becomes workarounds:

  • Generics via erasure or boxing
  • Value types as a decade-long project
  • Async as state machine rewrite theater

Mind blown: VM workarounds

Beskid pushes assembly output without IL handcuffs and compile-time power because we are tired of negotiating with a runtime that updates slower than the language.

Each layer promises you can forget below. Then production reminds you: GC, thread pools, HTTP/2, and disk still exist. You just debug them with worse symbols.

This is fine: production fog

Shoulders of giants implies visibility. Abstraction towers imply fog.

Beskid isn’t anti-abstraction, it’s anti-unpaid abstraction: layers you did not choose, cannot see in the binary, and cannot remove when the business rule is simple but the stack is not.

Next: 1.7 segfault or not to segfault.