The case against a C alternative (2022)
48 points - last Sunday at 3:17 PM
SourceComments
> 4. No experienced developers
Well, with C you need experienced devs that are also EXPERIENCED IN C. You can write C that compiles but is all kinds of incorrect, usually subtly. Any new language that works with the dev on writing correct code or outright refuses to compile with incorrect code (hinting at Rust here) cracks this egg a bit.
> If you want to target some obscure platform, then likely it's assuming you're using C.
Some (most?) obscure platforms offer a fork of GCC, yes. With LLVM frontend becomes less and less relevant. This particular chicken and an egg is being broken with or without a successor to C.
> Any C alternative will be expected to be on par with C in performance. The problem is that C have practically no checks, so any safety checks put into the competing language will have a runtime cost, which often is unacceptable. This leads to a strategy of only having checks in "safe" mode. Where the "fast" mode is just as "unsafe" as C.
This argument is circular. There are indeed some scenarios where you do absolutely need "macro system for assembly" to do some weird shit, but typically that is a relatively small part of the whole project. Unsafe modes help tackle this small need. The argument reads like needing C-ish language for some little parts of your project requires to use C-ish language for the whole project.
> 3. Programmer productivity
This whole argument is weirdly focused. In my experience, a huge chunk of effort is spent on rework. Any language that improves turnaround rate improves productivity on feature level. The argument again assumes that devs manage to produce correct code without turnarounds (which is rare in practice even with highly experienced devs) and therefore any new language would increase turnarounds. Safety and productivity features are usually designed to increase quality without expertise-floor.
I miss one of the most important points for me:
C is a very easy to learn programming language (I explicitly do not claim that it is easy to write correct/bug free programs in C) and for me even more important: The mental model of a computer/abstract machine that C exemplifies (memory, pointers, pointer arithmetic, functions) is unbelievably useful for understanding and coming to terms with nearly all kind of programming languages/computer programs. Of course the mental model is wrong, but boy is it useful.
Would I start a new project in C if I can help it? Never. Would I use any other language than C if I want to implement a small part of a program which benefits from a C like low level language? I would not say never, but I do not see any candidate language at this moment. Especially because small programs in C IMHO are manageable for a reasonable experienced programmer.
I would love to life in an alternate reality where something like LISP/Scheme would be the basic model of computation (lambda calculus) and everything else would build on this as a useful mental model, though! :-)
But obviously nothing will replace C in the sense that C will cease to exist.
Is there a modern language with ABI stability that can replace C for that? As in, you can wrap anything with a C API and be sure that it can be called from any other language easily?
This problem is overstated. There's no safety/performance tradeoff here. Rust has shown that extensive safety checks can be applied at compile time with zero runtime overhead.
For a concrete example, checking that an array access is in bounds at runtime does come with a performance penalty. However it's also possible to prove at compile time that an array index can never escape it's array bounds. And, if it's not possible to prove this statically - you should be heavily questioning the security of that code.
Zig seems to be most prominent C alternative today, well funded, with some high-profile support, excellent engineering and both a loyal fanbase and haters.
That said, as longtime C user, I've been tempted by Jai and Zig and C3, but I am not ready to make the switch yet. The benefits are simply not big enough.
And there is something new that was not apparent in when this article was written: a lot of code is LLM written now, giving old and mainstream language an undeniable advantage. Also, Rust, with the built-in safeguards, is pretty AI assistance friendly.
Rust made the mistake of thinking it can be low level AND safe. It tried to have the cake and eat it too. That will be its downfall.
In the case of established codebases the issue is that we don't want to rewrite them because they're huge and not very well designed usually. There are no unit tests or not many and we cannot break ABI compatibility and so on. So change has a risk. Also you're trying to get other developers to agree to the change and they are often in a post-nuclear-war state about other technical decisions and certainly don't want to start another one about some language they don't understand.
What we really need is some way to progressively improve big codebases without having to swallow a huge pill. In other words I need to be able to work a file at a time with something that fits exactly into the build system that is building the C code.
At the moment I'm using ESQL to embed Informix queries - this is a subtly quite good language extension that certainly makes life better except of course that it ties us to a specific expensive database etc etc. As an improvement on C it works in it's limited sphere.
In this huge project there's so much code that it's hard to know what's the right way to do anything and the same solutions have been written again and again in slightly different ways.
Half the libraries have circular dependencies such that they only build with an odd little trick and it's extremely difficult to know the precise reasons why this design evolved or how to begin unpicking those dependencies. Without tests any change could be a disaster.
One established way of improving on C is to use a DSL or something like embedded TCL such that most of the time you're not actually writing C. The current project went the DSL route and it's very very much better than nothing but without a grammar the parser is hard to maintain. I've been on a project using TCL and that was excellent - loading and parsing a config file, for example, is something one almost never really needs to do in C and there are many bits of a program that TCL can do much more reliably and perfectly fast enough.
This ramble is trying to convey that a new language presents a problem to people who have 100 problems already. If you can make it help with those 100 problems then it will win.
Successful example: Converting to Git from SCCS is a huge pain but I've just done it (had to infer changesets from individual file version usernames and dates and times :/ ) but Git is well worth the trouble because it's so much less stressful to make mistakes with and vastly easier to do reviews and so on.
Rust was made to replace C++ because the language it's a behemoth, it tries to do everything and the syntax it's a Lovecraftan nightmare, full of legacy incompatibilities. For small games such as Cataclysm:DDA I'd use Go (and for system tools and internet services OFC) and for game engines Rust it's or even GC based languages (not Java) can do it well (C# with AOT).
Even Common Lisp it's fine (just look up Trial/Kandria) with SDL2/3 and/or OpenGL bindings (Vulkan ones should be somewhere). Pick SBCL for speed, learn CL, learn about SIMD and optimizations. It can beat C on performance.
https://www.stylewarning.com/posts/nbody/
EDIT: the bindings are cl-vulkan, of course.
For instance:
"The C language is not just the language itself but all the developer tools developed for the language. Do you want to do static analysis on your source code?"
This is a finite problem set. For instance, AI could auto-create useful toolings eventually. And even without AI, people can. Even more so if a new language is designed with that in mind from the get go. So, perhaps it would be a lot of effort, but this is really not the reason why C is so dominating.
> The uncertainties of a new language
> Before a language has matured, it's likely to have bugs and might change significantly to address problems with language semantic.
Here I somewhat agree. Another language is different, that is true, and may not be better, that is also true. I am still not convinced Rust is better than C, for instance.
However had, I also don't this this as unsolvable. Many new languages are in part better than C. I mean, I notice this when I write ruby code and C code. Let's ignore the speed problem; and the fact that ruby is written mostly in C (which kind of shows that C dominates everything). The ruby code I write is about 1000000000x easier to understand, simpler and almost always shorter than C. There is no comparison here. Ruby is the better programming language. C is faster and more efficient. And this is also significant. My prediction is that a language that would be able to replace C, needs to target both the speed issue without compromise AND the efficiency of writing code, be it ruby-like, python-like and so forth. And neither of these two languages try to replace C either, so they don't quite count here.
> And what about maintainers? Sure, an open source language can be forked, but I doubt many companies are interested in using a language that they further down the line might be forced to maintain.
This is a problem, but you have this problem with corporations too. For instance, Go is controlled by Google, as is Flutter/Dart. Google can babble that everyone can contribute but the reality of the situation is that Google decides what happens; same with the adChromium code base. Personally I really don't want corporations to dictate their world view onto a language. Committees can also have problems or be bribed and what not, we can see the chaos in the C++ committee too, even without bribery - stupidity often rules supreme. But by and large, I much prefer single benevolent dictators or indepedent (as much as possible) committees than mega-evil mega-huge greedy corporations controlling a language. This does not automatically mean a language is better or worse, either way, but it is a preference for me. And I know for a fact that many others somewhat or strongly agree with this too, except a few die-hard Google fanbois (but most of them are employed by Google anyway, so their "opinion" does not count; I see the same problem with shopify and ruby, by the way, it's really interesting).
> 3. The language might just not be good enough > Is the language even addressing the real pain points of C? It turns out that people don't always agree on what the pain points with C is.
Yup, that is also true, see Rust. On the other hand, I think cargo is really useful, and even C++ agreed. I think C also did not that long ago, but boy, for many decades C thought that easy download of add-ons is not needed. C changes very slowly. I understand that this is often nice, but just as in the example of cargo and what not, this was really STUPID of C to not change here.
Other than that I agree on the general point. Many changes are also idiotic in other languages. Ruby incorporated many idiotic changes too; thankfully I can avoid most of them so I just ignore them indeed.
> A new language will naturally have a much smaller pool of experienced developers. For any middle to large company that's a huge problem. The more developers there are available for a company, the better they like it.
That's also true, e. g. look how few developers use D. I think the only way to change this is to make the language SIMPLE, EASY but also efficient at the same time. Like python. Though python is not aiming to be a replacement of C, so it does not count - but people are quite easily able to learn and use it. C is much harder to use; just give new recruits a task to implement things that manipulate memory and pointers a lot.
> The C ABI is the standard for interoperability
Any language can have that too so I don't see this as a problem.
> 1. Better syntax
> Having a "better syntax" than C is mostly subjective.
Wrong. And this is what 99% of those "I will replace C with my language XYZ" get wrong. The syntax they use usually SUCKS. They think syntax matters absolutely not at all. They are wrong. But they think they are right, so they write a useless pile of crap and then wonder why nobody writes in that language.
> 2. Safer than C > Any C alternative will be expected to be on par with C in performance. The problem is that C have practically no checks, so any safety checks put into the competing language will have a runtime cost, which often is unacceptable.
This is partially correct, partially wrong. Rust showed that safety is a feature; C++ agreed. C does not. I understand the speed penalty, and I am not saying you need to make safety a pseudo-religion like Rust did, but that trade-off needs to be determinable by the code author. So, some code can be fast like in C; for other code the trade-off may be different. A language should make it super-easy to distinguish here. Rust does not make it super-easy. C even less.
> Programmer productivity
> First of all, pretty much all languages ever will make vacuous claims of "higher programmer productivity". The problem is that for a business this usually doesn't matter. Why? Because the actual programming is not the main time sink. In a business, what takes time is to actually figure out what the task really is. So something like a 10% or 20% "productivity boost" won't even register. A 100% increase in productivity might show, but even that isn't guaranteed.
Also totally wrong. Yes, writing code is not always the bottle neck, but what he forgets is the simplicity of writing good, fast code. If it takes 5 hours to write 3 lines of code, something is wrong with the language itself.