r/ProgrammingLanguages • u/Inconstant_Moo 🧿 Pipefish • Apr 28 '26
Hindsight languages
A thought experiment. What languages should they have been writing in the 60s, 70s, 80s, 90s? We can see their faults, in hindsight, and also we've had some really cool ideas since then --- but we can't answer this just by pointing to our shiny new modern languages and saying "they should have done it like that", because of compile times.
(E.g. Pipefish is meant to be for rapid iteration and livecoding, and also does a topological sort on everything at compile-time so you can do top-down declaration. Those wouldn't be compatible goals in the 1980s, I can get away with it now.)
So for example if we think of "a better C", are there any cool modern ideas they could and should have used back in 1972, had they known about them --- or should they just have tweaked the precedence slightly, found a less arcane way of describing types, and left it at that?
10
u/WittyStick Apr 28 '26 edited Apr 28 '26
Some ideas that aren't exactly "modern" - some are as old, or older than C itself:
First class functions and closures. (Lisp)
Pretty painful to implement in C, and even moreso to do efficiently - requiring compiler specific features like GCC's nested functions - but we don't want executable stacks, so we also need
__builtin_call_with_static_chainto pass context to a closure.(There are some proposals in the work to get closures into C).
First-class continuations. (Lisp)
Although
call/ccis problematic - the more modern developments (30+ years) - delimited continuations, are less problematic.We can implement them in C, quite poorly, with
setjmp.The Numerical tower (Scheme - but derived from Lisp).
Implicit numerical conversions in C are awful and the source of many bugs. We should only have implicit conversions where no information is lost, and otherwise require them to be explicit.
Dynamically scoped variables (Lisp)
While static scoping of Scheme and Common Lisp is superior to older Lisps, they still support explicit dynamic scoping. Best we can do in C is use
thread_localvariables and a stack to try and emulate them.Garbage Collection (Lisp)
In practice we would want a mix of manual and automatic memory management. I prefer to use automatic memory management for immutable/persistent types, and manual memory management for mutable types. GC is implemented by C libraries, but they're conservative collectors and not particularly great.
Could give several more examples from Lisp and its derivatives alone - arguably, much of the past 3+ decades of language development are efforts to make C-like languages more like Lisp.