Live data from Hacker News

Matt Godbolt sold me on Rust by showing me C++

collabora.com

501–510 of 675 posts

Re: Matt Godbolt sold me on Rust by showing me C++

#501

All this has been known in the PL design community for decades if not half a century by now. Two things are incredibly frustrating when it comes to safety in software engineering: 1. The arrogance that "practitioners" have against "theorists" (everyone with a PhD in programming languages) 2. The slowness of the adoption of well-tested and thoroughly researched language concepts (think of Haskell type classes, aka, Ru…

It's weird that this sort of debate around C++ often leaves out the fact that many of the problems with C++ were known before C++ even existed. Outside of a few specific buckets, there is no reason to use C++ for any new projects, and really, there never has been. If you can't stomach Rust for some reason, and I'm one of those people, there are plenty of choices out there without all the pitfalls of C++ or C.

> If you can't stomach Rust for some reason, and I'm one of those people, there are plenty of choices out there without all the pitfalls of C++ or C.

Unless you are doing embedded programming ...

Re: Matt Godbolt sold me on Rust by showing me C++

#502
post #357

Earlier quoted context omitted.

Sure, but it is pragmatic in other ways as well :) It takes ADT, but not function currying, and so on.

I've occasionally wondered about the lack of currying in Rust; it feels like something that can be done mechanically at compile time, so why not support it? Perhaps to do it cleanly (without more magical privileged functions in core) would require variadic generics?

This isn’t Rust-specific, but one reason a language designer might deliberately not implement currying is that it makes function call sites a bit harder to read. You need to already know how many arguments a function takes to make sense of the call’s return type.

Re: Matt Godbolt sold me on Rust by showing me C++

#503
post #280

Earlier quoted context omitted.

Yes, people keep forgeting C++ was made public with CFront 2.0 back in 1989, 36 years of backwards compatibility, to certain extent.

C++ is C compatible so more than 50 years of backward compatibility. Even today the vast majority of C programs can be compiled as C++ and they just work. Often such programs run faster because C++ a few additions that the compiler can use to optimize better, in practice C programs generally mean the stronger rules anyway (but of course when they don't the program is wrong).

CFront was never compatible with K&R C to the best of my knowledge, so the actual start date would be whenever C89-style code in widespread use; I'm not sure how long before 1989 that was.

Re: Matt Godbolt sold me on Rust by showing me C++

#504
post #304

Earlier quoted context omitted.

And? I don't really see the issue. It works, it is sound, and it has a nice clean interface for safe code to use. That's all I really ask for. Lots of useful things in programming are quite gnarly under the hood, but that doesn't mean those things aren't worth using.

It is fine, there is just not much Rust safety advantage left then. Also in C/C++ the errors do not usually occur when using a nicely defined API, but when doing the low-level gnarly stuff and getting it wrong. As said before, I think there is some advantage of Rust having a safe and unsafe subset, but is is nowhere as big as people claim it is.

> It is fine, there is just not much Rust safety advantage left then.

There's exactly as much as there was before though. The entire point of the Rust safety paradigm is that you can guarantee that unsafe code is confined to only where it is needed. Nobody ever promised "you will never have to write unsafe code", because that would be clearly unfeasible for the systems programming domain Rust is trying to work in.

I frankly cannot understand why people are so willing to throw the baby out with the bathwater when it comes to Rust safety. It makes no sense to me to say "my code needs to have some % unsafe, so I'll just make it 100% unsafe then" (which is effectively what one does when they use C or C++ instead). Why insist on not taking any safety gains at all when one can't have 100% gain?

Re: Matt Godbolt sold me on Rust by showing me C++

#505

This is actually the point where Rust starts to frustrate me a little bit. Not because Rust is doing anything wrong here, but because the first well-known language to really get some of these things right also happens to be a fairly low-level systems language with manual memory management. A lot of my colleagues seem to primarily be falling in love with Rust because it's doing a good job at some basic things that hav…

> Not because Rust is doing anything wrong here, but because the first well-known language to really get some of these things right also happens to be a fairly low-level systems language with manual memory management. It also has half implementations of all the useful features (no distinct enum variant types, traits only half-exist) because you have to code to the second, hidden language that it actually compiles to.

Yeah, I've hit the enum variant type issue myself (e.g. a function guaranteed to return one of the variants), but in practice it hasn't been that big of an issue. There's also std::mem::discriminant [1] which helps a bit.

What do you mean by traits only half-existing?

[1] https://doc.rust-lang.org/stable/std/mem/fn.discriminant.htm...

Re: Matt Godbolt sold me on Rust by showing me C++

#506

Earlier quoted context omitted.

I agree these things would be better, but I don’t understand how anyone can think UB is better than abort. (Going to moan for a bit, and I realise you aren’t responsible for the C++ standards mess!) I have been hearing for about… 20 years now that UB gives compilers and tools the freedom to produce any error catching they like, but all it seems to have done in the main is give them the freedom to produce hard to debu…

A lot UB is things you wouldn't do anyway. While it is possible to define divide by zero or integer overflow, what does it mean. If you code does either of those things you have a bug in your code (a few encryption algorithms depend on specific overflow behavior - if your language promises that same behavior it is useful). Since CPUs handle such things differently whatever you define to happen means that the compiler…

This is a bad answer too, IMO.

I think there is a solid case for the existence of undefined behavior; even Rust has it, it's nothing absurd in concept, and you do describe some reasoning for why it should probably exist.

However, and here's the real kicker, it really does not need to exist for this case. The real reason it exists for this case is due to increasingly glaring deficiencies in the C++ language, namely, again, the lack of any form of pattern matching for control flow. Because of this, there's no way for a library author, including the STL itself, to actually handle this situation succinctly.

Undefined behavior indeed should exist, but not for common cases like "oops, I didn't check to see if there was actually a value here before accessing it." Armed with a moderately sufficient programming language, the compiler can handle that. Undefined behavior should be more like "I know you (the compiler) can't know this is safe, but I already know that this unsafe thing I'm doing is actually correct, so don't generate safeguards for me; let what happens, happen." This is what modern programming languages aim to do. C++ does that for shit like basic arithmetic, and that's why we get to have the same fucking CVEs for 20+ years, over and over in an endless loop. "Just get better at programming" is a nice platitude, but it doesn't work. Even if it was possible for me to become absolutely perfect and simply just never make any mistakes ever (lol) it doesn't matter because there's no chance in hell you'll ever manage that across a meaningful segment of the industry, including the parts of the industry you depend on (like your OS, or cryptography libraries, and so on...)

And I don't think the issue is that the STL "doesn't care" about the possibility that you might accidentally do something that makes no sense. Seriously, take a look at the design of std::variant: it is pretty obvious that they wanted to design a "safe" union. In fact, what the hell would the point of designing another unsafe union be in the first place? So they go the other route. std::variant has getters that throw exceptions on bad accesses instead of undefined behavior. This is literally the exact same type of problem that std::expected has. std::expected is essentially just a special case of a type-safe union with exactly two possible values, an expected and unexpected value (though since std::variant is tagged off of types, there is the obvious caveat that std::expected isn't quite a subset of std::variant, since std::expected could have the same type for both the expected and unexpected values.)

So, what's wrong? Here's what's wrong. C++ Modules were first proposed in 2004[1]. C++20 finally introduced a version of modules and lo and behold, they mostly suck[2] and mostly aren't used by anyone (Seriously: they're not even fully supported by CMake right now.) Andrei Alexandrescu has been talking about std::expected since at least 2018[3] and it just now finally managed to get into the standard in C++23, and god knows if anyone will ever actually use it. And finally, pattern matching was originally proposed by none other than Bjarne himself (and Gabriel Dos Reis) in 2019[4] and who knows when it will make it into the standard. (I hope soon enough so it can be adopted before the heat death of the Universe, but I think that's only if we get exceptionally lucky.)

Now I'm not saying that adding new and bold features to a language as old and complex as C++ could possibly ever be easy or quick, but the pace that C++ evolves at is sometimes so slow that it's hard to come to any conclusion other than that the C++ standard and the process behind it is simply broken. It's just that simple. I don't care what changes it would take to get things moving more efficiently: it's not my job to figure that out. It doesn't matter why, either. The point is, at the end of the day, it can't take this long for features to land just for them to wind up not even being very good, and there are plenty of other programming languages that have done better with less resources.

I think it's obvious at this point that C++ will never get a handle on all of the undefined behavior; they've just introduced far too much undefined behavior all throughout the language and standard library in ways that are going to be hard to fix, especially while maintaining backwards compatibility. It should go without saying that a meaningful "safe" subset of C++ that can guarantee safety from memory errors, concurrency errors or most types of undefined behavior is simply never going to happen. Ever. It's not that it isn't possible to do, or that it's not worth doing, it's that C++ won't. (And yes, I'm aware of the attempts at this; they didn't work.)

The uncontrolled proliferation of undefined behavior is ultimately what is killing C++, and a lot of very trivial cases could be avoided, if only the language was capable of it, but it's not.

[1]: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n17...

[2]: https://vector-of-bool.github.io/2019/01/27/modules-doa.html

[3]: https://www.youtube.com/watch?v=PH4WBuE1BHI

[4]: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p13...

Re: Matt Godbolt sold me on Rust by showing me C++

#507

Earlier quoted context omitted.

It's weird that this sort of debate around C++ often leaves out the fact that many of the problems with C++ were known before C++ even existed. Outside of a few specific buckets, there is no reason to use C++ for any new projects, and really, there never has been. If you can't stomach Rust for some reason, and I'm one of those people, there are plenty of choices out there without all the pitfalls of C++ or C.

> If you can't stomach Rust for some reason, and I'm one of those people, there are plenty of choices out there without all the pitfalls of C++ or C. Unless you are doing embedded programming ...

I think embedded is one of the specific buckets.

You target the compiler your client uses for their platform. There is very little choice there.

Re: Matt Godbolt sold me on Rust by showing me C++

#508
post #304

Earlier quoted context omitted.

And? I don't really see the issue. It works, it is sound, and it has a nice clean interface for safe code to use. That's all I really ask for. Lots of useful things in programming are quite gnarly under the hood, but that doesn't mean those things aren't worth using.

It is fine, there is just not much Rust safety advantage left then. Also in C/C++ the errors do not usually occur when using a nicely defined API, but when doing the low-level gnarly stuff and getting it wrong. As said before, I think there is some advantage of Rust having a safe and unsafe subset, but is is nowhere as big as people claim it is.

Is there a safety advantage to using Java given that the HotSpot JVM is written in C++?

All safe code is built on a foundation of unsafe code.

Re: Matt Godbolt sold me on Rust by showing me C++

#509

Earlier quoted context omitted.

The functions are so verbose and inconvenient that even Rust developers themselves do not use them. For example, in this code [1] they used a wrapping addition instead of "checked_add" because it is faster to write. For comparison, Swift uses "+" for checked addition and as a result, majority of developers use checked addition by default. And in Rust due to its poor design choices most developers use wrapping additio…

Checked addition by default will have too much overhead and it will hurt performance, which unacceptable in Rust since it was designed as a system language. Swift can use checked add by default since it was designed for application software. Your example code is not because it is faster to write, it is because it is impossible for its to overflow on that line.

Why should checked addition have any overhead? You should just use checked addition instruction (on architectures that support it) instead of wrapping addition.

Or just because on Intel CPUs it has overhead, we must forget about writing safer code?

Re: Matt Godbolt sold me on Rust by showing me C++

#510

Earlier quoted context omitted.

I agree these things would be better, but I don’t understand how anyone can think UB is better than abort. (Going to moan for a bit, and I realise you aren’t responsible for the C++ standards mess!) I have been hearing for about… 20 years now that UB gives compilers and tools the freedom to produce any error catching they like, but all it seems to have done in the main is give them the freedom to produce hard to debu…

> but why not just enforce that as standard I don’t think people want that as standard. The whole point of using C++ tends to be because you can do whatever you need to for the sake of performance. The language is also heavily driven by firms that need extreme performance (because otherwise why not use a higher level language) There are knobs like stdlib assertions and ubsan, but that’s opt-in because there’s a cost…

There does not need to be an additional cost for this.

Most users will do this:

1. Check if there is a value

2. Get the value

There is nothing theoretically preventing the compiler from enforcing that step 1 happens before step 2, especially if the compiler is able to combine the control flow branch with the process of conditionally getting the value. The practical issue is that there's no way to express this in C++ at all. The best you can do is the visitor pattern, which has horrible ergonomics and you can only hope it doesn't cause worse code generation too.

Some users want to do this:

1. Grab the value without checking to see if it's valid. They are sure it will be valid and can't or don't want to eat the cost of checking.

There is nothing theoretically preventing this from existing as a separate method.

I'm not a rust fanboy (seriously, check my GitHub @jchv and look at how much Rust I write, it's approximately zero) but Rust has this solved six ways through Sunday. It can do both of these cases just fine. The only caveat is that you have to wrap the latter case in an unsafe, but either way, you're not eating any costs you don't want to.

C++ can do this too. C++ has an active proposal for a feature that can fix this problem and make much more ergonomic std::variant possible, too.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p26...

Of course, this is one single microcosm in the storied history of C++ failing to adequately address the problem of undefined behavior proliferating the language, so I don't have high hopes.

Post reply on HN