On Programming Languages
Some thoughts on why languages exist, why there are so many, and how you'd build one.
1.
Why did we move from punch cards to programming languages? What does that
tell you about the purpose of programming languages?
We moved away from punch cards because physical slips of paper were
fragile, impossible to modify without repunching, and rigidly bound to
specific hardware architectures. That transition reveals that programming
languages are fundamentally designed for human cognition, not machine
efficiency. Computers only require binary signals, so high-level languages
exist as an abstraction layer that lets people reason through algorithms,
variables, and data structures rather than manual memory offsets.
2.
There are hundreds of different programming languages out there. Why do
you think we need so many?
We need so many languages because every software domain demands a
different balance of trade-offs. Writing real-time embedded firmware
requires direct hardware control and manual memory allocation, whereas
rapid data science calls for flexible, interpreted scripting, and large
distributed backends benefit from built-in concurrency primitives. No
single language can optimize for maximum hardware performance, rapid
developer iteration, and strict safety guarantees all at once.
3.
What are some drawbacks of a programming language you use? How would you
like it to be different? Think of specific examples.
In C++, the biggest drawback is that its pursuit of raw performance leaves
memory management almost entirely unconstrained, meaning a minor typo like
accessing an index past an array's boundary silently corrupts memory
through undefined behavior instead of throwing a clean compiler error. If
redesigned, it would incorporate modern compile-time ownership rules by
default to prevent dangling pointers entirely, along with a standardized,
built-in module and package manager to replace fragile preprocessor
header inclusions.
4.
If you were going to create a new programming language, how would you
start? What do you need to define?
You would start by defining the language's target niche, execution
model — whether interpreted or compiled — and its type and memory safety
guarantees. From there, you must establish the formal grammar syntax,
build a lexer and parser to transform raw code into an abstract syntax
tree, implement a semantic analyzer to enforce type rules and scoping,
and finish by writing either a virtual machine interpreter or an
intermediate representation backend like LLVM to emit executable machine
code.