Hacker News new | ask | show | jobs
by pron 1611 days ago
I'm not quite sure who this article is aimed at, and who those "C++ apologists" are, but as someone who programs in C++ all day, doesn't like it at all, and yet won't advocate to switch to Rust, these kinds of arguments are unconvincing. I'm not advocating to switch to Rust not because I don't think it's better than C++. I am absolutely, 100% convinced that Rust is technically better than C++ in most possible ways — in some, significantly better — and worse in almost no way. The problem is that, overall, it's not better enough.

Reevaluating a low-level programming language is something that's done in a large organisation or project once every 15-25 years or so. Switching such a programming language incurs a high cost and a high risk, and is a long-term commitment. To make such a switch, the new language obviously has to be better, but that's not enough. It has to be a hell of a lot better (and, if not, at least return the investment with a profit quickly).

For some, Rust is better enough. For me, not nearly so. Even though it offers a fascinating and, I think, ingenious path to better safety, it shares some of C++'s greatest downside for me, which is that they are both extremely complex languages. Maybe Rust is simpler, but not enough. Rust also shares what I think is C++'s original misguided sin, which is the attempt to create a low level language, whose code appears high-level on the page by means of a lot of implicitness. I've become convinced that that's a very, very bad idea.

If there were no other ideas on the horizon or if Rust seemed like a surefire success, it might have been justified to make such a switch, but that's not the case. Rust's low adoption rate in professional settings is not reassuring to "PL-cautious" people like me, and a language like Zig shows that there are other approaches that appeal to me more, and while more revolutionary and ambitious than Rust in its departure from C++'s philosophy, I think it also has the potential to be better enough. Maybe it will make it, and maybe it inspires some other language that will, or maybe other ideas will turn up. Given the risk and commitment, to me it makes sense to wait. I don't like C++; I believe Rust is better. But that's not enough.

5 comments

Every large project with years of code (legacy or well maintained) will be hardly ever re-written with complete success. It's not a property of programming language in my opinion. It's just economic sense. I doubt JDK will be rewritten in Rust/Zig, they did GraalVM in Java though.

Zig might be revolutionary but personally for me Rust is why I can dare write non gc code. I never thought I would ever be robotically precise with memory management on a large project in memory unsafe languages, that doesn't change with Zig. There are experts in C/C++, there will be experts in Zig and we will continue having memory safety CVEs because they don't make mistakes/they can use some other static analysis tool/they can test :)

I think people comfortable writing low level code under appreciate what Rust has done for bystanders or newcomers or a large team. It is definitely complex but choosing C/C++/Zig over it would make even less sense since lack of guardrails.

Even if you look just at sound language guarantees, Zig is closer to Rust in terms of memory safety than to C or C++. That it doesn't make all of Rust's static guarantees doesn't put it in the same bucket as languages that make none. Once you reduce memory safety issues to below half of their current rate, there are different paths to achieving a good overall correctness story.
Zig is no way closer to Rust than C or C++ in this regard. Zig is in fact not appreciably safer than C or C++. All of the same classes of memory safety problems that are present in C or C++ are present in Zig.

I am extremely doubtful of the claim that Zig eliminates 50% or more of memory safety problems.

As (safe) Zig eliminates overflows just as (safe) Rust does, and, like Rust, has not unsafe casts, I don't see how "all of the same classes of memory safety problems that are present in C or C++ are present in Zig." Also, Zig guarantees — just as Rust does — that all pointers and means of creating them are known, and precisely so, so analysis tools could work on Zig better than they do on C or C++. In C/C++, at best they could check pointers at the time of dereferencing, while for Zig they could do so at the time of deallocation. You once said that couldn't work because Zig would have dangling pointers lying around (presumably in addition to the one used for deallocation) because C does, but it might as well be the case that C programs leave dangling pointers because tools cannot detect them, which has affected the programming style, not the other way around.

It's OK to doubt claims/hopes about Zig, just as I doubt the claim that Rust can achieve more correct/secure programs than Zig for less effort. Without empirical data, there's really no way to know. So in the meantime, all there is to go on is personal appeal. But you cannot support your claim that Zig is "just like C" with the assumption that it is.

I think that, at the end of the day, there is what we might call an "ideological" difference between us. While we both accept that both language features and best practices — code reviews, tests, tools — reduce bugs, we draw the line of where it's worth to sacrifice one for the other in different places. It might also be the case that Rust's complexity doesn't sacrifice anything for you, but it does for me, as I'm uncomfortable with complex languages, and I think Rust easily makes the top four most complex "production" languages in history (together with C++, Ada, and Scala). So while even for me C is on the wrong side of my line (just as Idris is on the wrong side of yours), I reject extrapolating from C to Zig, because Zig makes many more guarantees at the language level, so without pertinent data about Zig, the question cannot be settled. If I thought Zig was "like C," I wouldn't have found it promising and so intriguing, either.

Having said all that, I don't want it to sound as if I'm willing to bet on Zig right now. I'm far too risk-averse for that. But I wouldn't bet on Rust right now, either. What it brings to the table doesn't offset, for me, its (still-)high risk. All I'm saying is that the revolutionary Zig hints at a promise of a new low-level language that could bring more to the table and justify the risk.

P.S.

I guess we could summarise Rust's and Zig's core design hypotheses as follows: Even though both place the same emphasis on correctness, Rust doesn't compromise on memory safety (which, given what empirical data we do have, is an important component of correctness but certainly not equivalent to it), i.e. it adds all the sound language features needed to provide it, even at the cost of language complexity, while Zig doesn't compromise on language simplicity, i.e. it adds all the sound language features needed to provide memory safety up to the point they impact language complexity. I don't discount the possibility that there might be a language that could be safer than Zig yet less complex than Rust, or perhaps even as soundly-safe as Rust and as simple as Zig, but so far I haven't seen such a language.

Barring any empirical data, we cannot say which, if any, of those two approaches leads to better correctness (where by "better" I mean reaching the desired level of correctness needed for most low-level applications more cheaply), so we both lean on "ideology," where I prefer simplicity whereas you prefer sound guarantees — both of us in the name of correctness. I think we agree that both C and Idris are the wrong paths to correctness, but while we might reasonably disagree on the price we should pay for soundness, placing Zig's memory-safety in the same category as C's is just as exaggerated and misleading as placing Rust's soundness in the same category as Idris's.

By the way, I wouldn't at all be surprised if empirical research ends up finding no significant differences in correctness between the two, and, in fact, would guess it to be the most likely outcome given our inability to find significant bottom-line differences between "reasonable" same-generation languages so far.

> Even though both place the same emphasis on correctness

But they don't. At all. Rust treats correctness as paramount, not just memory safety (for instance, the existence of 6 different string types, or the PartialEq/Eq trait dichotomy are for correctness unrelated to memory safety). Zig doesn't.

Sure you can write correct programs in it, and that's what everybody wants, but the language doesn't make any efforts to make it easier than any others. Zig places as much emphasis on correctness as JavaScript[1], it's not C or C++ level of minefield, but when it comes to correctness the language won't help you.

Zig has cool (killer?) features like its seamless integration with existing C code, ease of cross compiling and a super cool metaprograming ability, there's no reason to oversell it on stuff it doesn't focus on: that's the best to disappoint people who'll try it.

In the same vein, talking about “safe Zig” vs safe Rust is misleading to the readers: all Zig is 100% unsafe by default, unless you compile it with ReleaseSafe or add a @setRuntimeSafety, and even if you opt-in to safety, the amount of safety is actually quite limited at the moment. There's a long time goal[2] to check for all kind of UB at runtime when safety checks are enabled, but it doesn't exist yet, and if you look at the afformentioned github issue, you'll see a bunch of “@andrewrk andrewrk removed this from the 0.x.0 milestone, added this to the 0.x+1.0 milestone”. At this point, the final vision of what “safe Zig” will look like isn't known yet! And unless Zig adopts a borrow checker or find an equivalent alternative (which would be super exciting, but is unlikely), it will incur costly runtime checks, making it undesirable in production as it will likely be slower than a regular managed language (it's not useless though, it will be like a better ASAN/UBSAN[3] that you can use during fuzzing, but pretty far from what Rust offers).

[1] and I say that as someone who spend a significant amount of time writing JavaScript for a living.

[2] https://github.com/ziglang/zig/issues/2301

[3] I say “better” because it would be strongly linked with the actual semantics of the languages (which can still change if the development of such tooling requires it) and not the retrofitted best-effort stuff you can have in C.

> Rust easily makes the top four most complex "production" languages in history (together with C++, Ada, and Scala)

Ada was "complicated" when it was released because it was being compared to C. Contrasting it against contemporary C++ or Rust, Ada 2012 is much simpler.

The language by itself, perhaps not, I don't know.

But, the fact that it has a test framework built in, and the test allocator fails when it detects memory problems (like a built-in valgrind) definitely puts it far above C in terms of making it easy to write correct code.

When I say that a language isn't meaningfully better than C in terms of memory safety, I mean C as programmed in 2022, which very much includes ASan.
You are misinformed. ASAN is a debugging tool. It is not a mechanism to provide safety to C applications.
It is the first time, I have heard of zig and I have to say, it indeed does sound nice. (But I haven't done low level programming in quite some time ..)

Can you maybe summarize a bit more, why you prefer it over rust?

The concept of rust, of beeing safe by default and only optimize critical parts sounds solid to me, but after a quick skimming, I have not seen such a feature for zig, too, possibly by design?

" No hidden control flow. No hidden memory allocations. No preprocessor, no macros."

I'm not OP, but the typical answer is that the language is small enough to be understood by any engineer with a few weeks of training, and is pretty easy for anyone familiar with C to grasp the concepts of almost immediately.

This is something that you definitely can't do with C++ and probably can't do with Rust.

For some people it's more comforting to be able to understand the entirety of the language and focus on the complexities of the problem and the implementation than to have a slightly higher level and larger language taking over the details. It's the same reason people tend to like C over C++ or Go over other languages.

This also generally translates into a couple of technical benefits as well, such as much much faster compilers relative to more complicated languages like C++ and Rust.

Personally I still find Rust much more comfortable to write code in generally but I really appreciate the elegance of the Zig approach.

It's mostly a matter of personal taste and values. I am extremely averse to language complexity, I dislike implicitness in low-level languages, and I value fast turnaround times. Others may have different values. I think Rust and Zig might appeal to different people, so you should see if you like it for yourself (it takes 1-2 days to fully learn), but note that it is absolutely not production ready (certainly not for me). I just find its approach refreshing and even surprising, and more in the direction of what I would hope would become the future of low-level programming.
> No hidden control flow

Oh boy and I was just reading (https://news.ycombinator.com/item?id=30022022) about ISO C unsuitability for OS programming specially its implicit reordering of the control flow of the code, breaking parts that are sensitive to the machine code generated.

I wonder if that point was introduce as a response for this ISO C nuance, does this means the machine code generated by ziglang code will be explicitly what each statement does?

> Rust is technically better than C++ in most possible ways — in some, significantly better — and worse in almost no way.

It's much worse in one way: Interoperation with existing C++ code. Sure, that's not a fair criteria - C++ is designed in a way that makes it almost impossible for other languages to use C++ libraries without a heavyweight wrapper like SWIG. However, even though it's not fair, it's still really important. If you have a project like LLVM with millions of lines of existing C++ code, adding expensive or complicated interop boundaries between different components within your system is not an acceptable price to pay.

Have you tried cxx? C++ interoperability in Rust has come a long way.
cxx is a huge improvement over manually writing bindings in C (with the inherent limitations imposed by C’s lack of expressiveness). At the same time, you still have to write a cxx::bridge to specify every boundary between Rust and C++ code, and the clients of on either side need to code against some generated code, not a simple .rs or .h file. It’s a huge improvement, but it’s still a lot more developer effort and boilerplate to use a C++ class from a Rust file than it would be to use that same C++ class from another C++ file.

cxx also can only handle a subset of the interfaces expressive in C++. If you haven’t written the interface with the specific goal of making it usable via cxx, it’s pretty likely you’ll have issues wrapping it with cxx.

Expecting a language be better "enough" is an unrealistic one, you will be waiting forever.

Of course no language will be perfect to a specific domain, there is no objective metric every individual has their own needs and no universal language can cater all them at once, there will be trade offs.

Rust is already better enough( and possibly will take decades before another language "suceeds" it), choose it or be on the perpetual expectation for a "perfect" language

> Expecting a language be better "enough" is an unrealistic one, you will be waiting forever.

Disagree. I think the "market" (the set of programmers) defines "enough". When a language is enough better (in some area, doesn't have to be all areas) you see widespread adoption.

C was enough better than PL/I, ALGOL, and assembly. Java was enough better than C++. (Why? Garbage collection, and the huge standard library.)

So far, Rust is not enough better than C++.

Now, I know this is kind of circular. I'm saying that a language is "enough" better if it wins in the market, and I'm saying that a language wins in the market if it's enough better. But I have some trust in programmers, that they are not just sheep. If a language is better than other languages in a way that matters to actual working programmers, a fair number of them will use it.

I neither a c++ programmer nor a rust one but I read things about programming. My take is that rust is near the breaking point where it becomes so commonly used that more teams and organizations will just start to use it.

The risk of switching for at least parts or a code base will seem low and then it probably looks better enough.

Of course some organizations and code bases are harder to change for some reason or reasons but many will probably start the conversion in the next 5 years. Unless rust just stops growing or something truly better comes along. I personally don't expect something much better soon and I think rust will continue to grow in usage.

> My take is that rust is near the breaking point where it becomes so commonly used that more teams and organizations will just start to use it.

You would have said the same thing about PHP or Ruby (or even that they're past their breaking point), and yet companies that are stuck with either one today aren't too happy about it. The problem is that these days, there are a lot of people who can switch languages without much risk. They switch to X, and tomorrow they switch to Y. While it's very good to have low-risk early adopters, having so many of them can really give a false impression about long-term risk. At some point, you need to see many "long-term committers" making a switch.

Some people ask, but how can you have many long-term committers if these risk-averse people also look around for others like them? The answer is that usually this isn't the main factor. If some technology indeed makes a big bottom-line impact, there's a competitive risk in not adopting it (because your competitors will and then beat you in the market), which is why big-benefit technologies spread quickly.

do you think “C” share the same that same miss guided sin?
No, there is very little implicitness in C. However, C suffers from other serious problems that Rust and Zig do address (and C++, too, to a lesser degree). It is extremely unsafe (more so than C++), and has a lower abstraction ability even compared to those other low-level languages.