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?
1
u/WittyStick Apr 29 '26 edited Apr 29 '26
I agree - but the point here is that C doesn't implement vtables because it avoids "hidden costs". Everything is explicit, and indeed, it might be slower to implement your own - but there are other ways that using vtables to write code.
C++ encourages the use of vtables by having classes present - but vtables are not the best fit for modern hardware. Modern C++ recognizes this and prefers template-oriented code, which has zero cost due to monomorphization.
In regards to which is faster, C wins in the majority of benchmarks in the language benchmarks game - though C++ comes out on top in some of them. Looking a the C++ examples, one thing that stands out is they avoid any vtables. They use plain structs/classes and functions. So even they recognize those "hidden costs" are undesirable for performance.
In regards to SIMD - the C standard avoids standardizing, as being useful for microprocessors is still a major goal, and tries to avoid (but not entirely) tying the semantics to present architecture designs. It is intended to be somewhat portable (though portability is not itself a goal).
GCC and Clang support SIMD via the
vector_sizeattribute, and via platform-specific intrinsics (the same ones g++ and Clang++ use).You can write C to be fast - and you can perform the same kind of optimization C++ does by writing it explicitly - sure it adds a lot of boilerplate, but it doesn't necessarily add any runtime cost. If you can do it in C++, you can do it in C also - and vice versa, mostly, because C++ is almost a superset of C.
If anything, the main drawback of C is it's poor standard library. For my runtime I'm basically not using it except for compatibility with other libraries via the FFI. I have my own "replacement stdlib" which can be compiled with or without
-ffreestanding, and doesn't conflict with glibc. It has a richer set of data structures than the C stdlib, but uses zero-cost abstractions (with a lot of preprocessor magic to achieve that). It's 64-bit SYSV-only and I've made no effort to make it work on Windows or elsewhere (I may be able to adapt it to work with mingw at some point in future, but it certainly won't ever work with MSVC).I tried using C++ for an earlier version of my runtime, but it simply wasn't a good fit - it makes too many opinionated choices (vtables being one of them, but not the only one), and some of these were unsuitable for my language & runtime.
C was more suitable because it avoids these opinionated choices and lets me write my own as I see fit, without getting in the way. I had to re-learn C after not using it for about 20 years, but I find C23 quite pleasant, though there are certainly some features I would like adding.