Rust is one of the best C replacements we currently have
This is a reply to the article published by Drew DeVault called “Rust is not a good C replacement”.
First of all, let me say that Drew is one of the people out there on the internet whose opinions I highly value. Indeed he is one of the people I try to read and listen to regardless of topic, because I think he is one of the people that deserve unconditional attention.
Needless to say that I've also read his latest piece “Rust is not a good C replacement”. I have to admit I was shocked at first, but after a bit of cooling down (and doing the dishes), I can see where this comes from.
And I have to disagree.
But let me start with my background – because that might be important for you, dear reader, to classify this article.
My background is mostly hobbyist programming. I did a few years of C, probably a few 100kloc, not more. I also do rust since about Rust 1.5.0 (2015-12). I started a job where I expect to write C and C++ professionally about 1 month ago.
So, I do not have a background like Drew with probably millions of lines of C, but I guess that I have a bit more experience with Rust – I wouldn't say that I'm a Rust professional, but I would consider myself a “Advanced Rust Hobbyist”.
I'm also not as skilled in writing blog articles or even with the english language, so keep that in mind when reading this.
I am not a big fan of statement-by-statement replying to an article, but I guess for this type of article it is good enough.
First of all, Drews initial statement that Rust was designed by C++ programmers: Yes, I absolutely see that this is true. Nevertheless I have to say that these C++ programmers started developing Rust because C++ was too complex and too error-prone in what it did and how it did it. Rust is far away from the complexity C++ gives us in terms of language features! From the top of my head, we have
- A full-blown OOP programming paradigm, including
- abstract classes
- partly and fully virtual functions
- pointers and references
- implicit conversions
- Copy/Move constructors
- Dynamic and static polymorphism
- Manual memory management
- Template Metaprogramming / Generic programming
- operator overloading
- Lambda expressions
in C++, whereas in Rust we only get
- Dynamic and static polymorphism
- operator overloading
- Lambda expressions
- Generic programming[^1]
You might consider this list cheated as Rust is not an object oriented language like C++, but an imperative one like C. That is very true. Nevertheless it is one reason why the cognitive load a C++-Program requires one to handle is much higher than an equivalent (as in features of the program) Rust program!
Drew claims that the values of C and C++ programmers are incompatible and I would agree with that. But that does not (have to) mean that a C-programmer and a Rust programmer do not have the same values. It is true, though, that Rust can excel at a lot of topics that C++ covers, but it also empower programmers that do not feel comfortable writing good C code to write their software. And that in a safe and at the same time performant language while not being overly blown up.
Further Drew compares C, C++, Go and Rust by their complexity, measured with features introduced in the language over the years. I am really sorry to say this here, Drew, but we are used to much better from you! You say that this approach (bullet points/features listed on wikipedia vs. bullet points in articles and release notes) is not very scientific, yes. But not even to mention the years these languages were released! For the record:
- C was released in 1972; 47 years ago
- C++ was released in 1985; 35 years ago
- Go was released in 2009; 9 years ago
- Rust was released in 2010; 8 years ago
I am not saying that this disproves your statement – it even supports it! But I do say that comparing based on features per year/release/whatever must include a statement about how old these languages are, even if it is just for showing the reader about what timeframe we are talking.
So, Rust is a relatively young language and yes, it has added a lot of features and therefore can be compared to C++ much better than it can be to C. But saying that a 10-year-old C programm might even compile today and everything might be okay but not so much with Rust is just ignorant of the fact that Rust is not even that old. Having a Rust program that is one year old still compiles fine today (assuming it didn't use a compiler bug) and does not “look old” at all! Rust has a big infrastructure for doing regression tests and for being compatible with older programs.
As you say, out of the way with the philosophical stuff and lets get down to the facts.
C is more portable. But as mentioned before, C is almost six times as old as Rust. We'll get there!
C has a spec. Yes, and I completely hear you on this one. Rust does not (yet?) have a spec and it really is a pain-point. I want one, too! Maybe we'll get there at some point. By the way: Does Go have a spec? It seems like it, but that rather looks like a language definition and I doubt that this is what Drew meant when talking about “a spec”, is it?
C has many implementations. Yes and how much trouble has it been because different compilers do different things on undefined behaviour? Too many. This is where Rust tries to solve a problem: Get a language where undefined behaviour is not allowed or at least as minimal as possible, then we can have a spec for that language and then we can have different implementations. Time will tell whether we can get there.
C has a consistent & stable ABI. Point taken. I do not argue about that.
Cargo is mandatory. Yes, another point taken. I again do not argue.
Concurrency is generally a bad thing. This statement gives me the impression that you did not yet try Rust, actually. Like in a big (and possibly multithreaded/concurrent/parallel/whateveryoucallit) environment. You say that most software does not have to be parallel and I fully agree on that – but if you need to be parallel, I'd rather chose Rust over Go, C or C++. Having the safety guarantees Rust gives me allows normal people (and not Rockstar-programmers) to write software that can be massively parallel without having to fear about deadlocks and other ugly things you get with other languages.
It is still true that bad design decisions are possible and might result in bad software – but that is true for every language, isn't it? And I'd rather like to have a bad program that gets the job done because it can be statically verified that it does than a program that crashes because I ran into a bug that was introduced by bad design decisions.
The next paragraph Drew writes makes me really, really sad. Fullquote:
Safety. Yes, Rust is more safe. I don’t really care. In light of all of these problems, I’ll take my segfaults and buffer overflows. I especially refuse to “rewrite it in Rust” – because no matter what, rewriting an entire program from scratch is always going to introduce more bugs than maintaining the C program ever would. I don’t care what language you rewrite it in.
This gives me the impression that Drew was hit with “Just rewrite it” too many times. And I completely agree with you, Drew, that you should indeed not rewrite it in Rust just for the sake. Nobody should ever rewrite anything in any other language than what “it” currently is written in. I hate these people that actually say things like that (if it isn't for trolling, but I have the uneasy feeling that Drew was hit with real “Just rewrite it”ers and not just trolling).
I do not say that the points Drew shows are false.
What I do say is that the initial assumption that Rust is there to replace C or C++ is, in my opinion, false. It is certainly meant to get things right that C++ got wrong – and it is certainly there to replace the C++-Monster that we call Gecko, because Mozilla is exactly trying to do that! But it is not there to replace all C or C++ code ever written because of some stupid “Hey we can do X better than your language” bullshit!
Also, the statement that Rust might end up as Kitchen-Sink like C++ and die with feature-bloat is one that concerns me because I do not want Rust to end up like C++. It certainly is not as complex as C++ and we (as in “the Rust community”) have a lot of work to do to not end up with feature-creep – but we are also certainly not there yet. But I definitively see where this statement is coming from.
The title of this article is “Rust is one of the best C replacements we currently have” – and I stand by this. But I also think that it is false to say that anyone has to replace C or that Rust is necessarily there to do so.
There are domains where you might want to rewrite C code, if you have the time and resources. But I'd rather advice against it[^3]. Improving existing code is always easier than a rewrite of a program and rewriting software does not improve the value of the software or even make customers more happy. Rewriting software is IMHO only legit in two cases:
- It makes you happy because you're doing it for fun
- It makes your boss happy because he ordered you to do so (for whatever reasons, may it be speed, resource usage, customer request or whatever)
But just for the sake of it? Nah.
I see where Drews article comes from and I see why he thinks like he does. I greatly value his opinion and thoughts, and that's why I took the time to write this article.
I see that we (as in “the Rust community”) have a lot to do to make more people happy. Not as in making them Rust programmers, because that's not our goal, but as in showing them that we do not want everything to be written in Rust and that it is just trolls that request a “rewrite in Rust”.
We do value friendlyness and kindness – let me state explicitely that this does also include other programming-language-communities (and all other communities as well)!
Trolling does not help with that.
[^1]: Yes we have generic programming in Rust. I'm not a professional regarding C++, so I cannot say whether they are comparable in this regard. [^2]: Some might say that we have manual memory management in Rust as well. That might be true by definition, but not the way I meant it: In C++ we can allocate something on the heap and then forget it. We have to try really hard to do that in Rust, though! [^3]: In fact I might get into the situation where I have to rewrite an application in my job, but I'd rather rewrite it in the same language than switching languages just for the sake of it!