Live data from Hacker News

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

collabora.com

581–590 of 675 posts

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

#581
post #383

I always enjoy reading articles like this. But the truth is, having written several 100s of KLOC in C++ (i.e., not an enormous amount but certainly my fair share) I just almost never have problems with this sort accidental conversion in practice. Perhaps it might trip me up occasionally, but will be noticed by literally just running the code once. Yes, that is an extra hurdle to trip over and resolve but that is triv…

This article presents something I’d expect competent C++ programmers with a few years of experience to know. Unfortunately, many programmers are not competent. And the typical modern company will do anything in its power to outsource to often the lowest bidder, mismanage projects and generally reduce quality to the minimum acceptable to make money. That’s why one needs tools like Rust, Java, TypeScript, etc. Unfortun…

This is my observation too:

> Rust is still too hard for the average programmer

What's the best way to "onboard" average programmers to Rust? Is it possible to avoid the more complex syntax and still be productive?

Or does Rust require us to fire and replace our "average c++ programmers" with super-smart Rust programmers?

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

#582
post #440

Earlier quoted context omitted.

You can use anyhow, but yeah zig generally does errors better IMO

Errors are where I find zig severely lacking. They can't carry context. Like if you're parsing a JSON file and it fails, you can know that it failed but not where it failed within the file. Their solution in the standard library for cases like this was to handle printing to stderr internally, but that is incredibly hacky.

The std has diagnostics struct you can give to the json parser. Zig is manually memory managed language so it doesnt have payloads in errors for a good reason.

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

#583
post #8

The one thing that sold me on Rust (going from C++) was that there is a single way errors are propagated: the Result type. No need to bother with exceptions, functions returning bool, functions returning 0 on success, functions returning 0 on error, functions returning -1 on error, functions returning negative errno on error, functions taking optional pointer to bool to indicate error (optionally), functions taking r…

The result type is obviously insufficient for writing nontrivial programs, because nontrivial programs fail in nontrivial ways that need exceptional control flow. The result type does not work because you have to choose between immediate callers handling failures (they don't always have the context to do so because they're not aware of the context of callers higher up on the call stack) or between propagating all of your error values all the way up the stack to the error handling point and making your program fantastically brittle and insanely hard to refactor.

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

#584
post #192

Earlier quoted context omitted.

> When there are 3-4 parameters it is too much trouble to write the names. Sorry, I don't agree. First, code is read far more often than written. The few seconds it takes to type out the arguments are paid again and again each time you have to read it. Second, this is one of the few things that autocomplete is really good at. Third, almost everybody configures their IDE to display the names anyway . So, you might as…

They aren't even necessarily redundant. If you have argument names as part of the function name, they can be overloaded on - and this is much more readable than type-based overloading because it's all explicit. Swift uses this to great effect, e.g. here are some different ways to construct a string: String(repeating: "foo", count: 42); String(cString: zeroTerminatedBuffer); String(42, radix: 16); String(contentsOfFil…

Oooh. Nice. I forgot about the Smalltalk / ObjC / Swift usage of keywords for messages.

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

#585

Earlier quoted context omitted.

If we take “mature” to mean “old” then yes - C and C++ are certainly old. If we take “mature” to mean “good”, then my answer changes.

"Mature" means that it has mostly developed to its logical conclusion, and its warts are well-documented and understood, as are workarounds for them. It doesn't say anything about "good", although using mature tooling can be good because (for all the warts) you don't have the rug pulled from underneath you every couple of years, as seen in e.g. JS land.

I think C/C++ are mature in the sense that everyone has gotten tired of trying to fix these issues. But I think we're getting further and further from "well understood" as time goes on. Very few practicing software engineers understand all the nuances of header files, C files, object files, static and dynamic linking, and how different compilers & ABI targets interact with all of that stuff. To say nothing of configure scripts, makefiles, automake & autoconf, pkgconfig, cmake and ninja and all the rest.

Just today, I spent 2 hours trying to get an OS kernel (SeL4) to compile for ARM64. This is an officially supported platform. I ran into a series of problems:

- A recent update to sel4 meant I need to set -DCONFIG_ARM_TLS_REG_TPIDRU for thread-local storage. (Leaving it out is a compiler error). This flag isn't in the configuration script - and it took me awhile to figure out how to set it through cmake + ninja.

- The gcc-aarch64-linux-gnu toolchain was recommended somewhere in the docs. On newer versions of gcc, that pulls in libgcc_eh.a, which tries to use _dl_find_object - which is of course linux only. So the build fails.

- So I swapped to gcc14's aarch64-none-elf cross compiler toolchain, which doesn't assume a dynamic linker is available. gcc-aarch64-none-elf isn't available in apt for some reason, even though the 32 bit counterpart is. From there, I ran into a new compiler error. Turns out the arm gcc toolchains are built against an old version of binutils that didn't have support for SHF_GNU_RETAIN. That is needed for the retain macro to work in C. And retain is used by sel4. This is just a compiler warning, but because sel4 promotes all warnings to errors, the build fails. I could have built my own compiler with a newer binutils. But I ended up just disabling the warning, because you only live once. I briefly tried gcc11 because that's recommended elsewhere in the docs, but gcc11 has the same problem.

All of this headache was from trying to build sel4 - which is all straight C, and one of the highest quality C projects I've ever seen. The codebase is mathematically proven to be correct. But oh my goodness, what a horrendous mess it is trying to work with it. And of course, just to try and get the build process going, I needed to install multiple compilers, ninja, cmake, python and a bunch of random python packages, and google's 'repo' tool to manage dependencies. What is this junk.

Personally I'd prefer to work with clang, but I've had enough pain for one day. And I know swapping compilers will for sure break something else.

If sel4 was written in zig or rust, it would be 10x easier to build and work with. Zig handles cross compilation to any supported platform out of the box. Rust can install toolchains trivially with rustup. Rust also has consistent stability guarantees, ensuring code doesn't "rot" with new compiler versions. And of course, both handle dependencies much, much better. And no need for cmake / ninja / random python scripts to compile. Zig and rust also don't behave differently based on someone else's binutils version. Wtf.

If C is too "mature" to fix these problems, I'm going to switch languages. Sel4 is only 20k lines of code. I wonder if it'd be less work to port it to zig than work with it in C. (I'd consider rust, but rust code can't prevent panics.)

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

#586
post #546
post #285

Earlier quoted context omitted.

Yes, from safety point of view Rust is much better option, however from the ecosystems I care about (language runtimes and GPU coding), both professionally and as hobby, C++ is the systems language to go, using Rust in such contexts would require me to introduce extra layers and do yak shaving instead of the actual problem that I want to code for.

Well, precisely. Such is the price of "general-purpose safety". The biggest irony IMO is that the security features of Rust are so often skirted in the name of speed, efficiency, etc, with the end result being a program which isn't much more secure than its C++ equivalent. ¯\_(ツ)_/¯

It isn't the safety or lack thereof, rather really adding another toolchain, development and debugging complexity.

Lets say I am doing something with V8, CLR, JVM, GCC, LLVM, CUDA, Metal, outside the managed languages that sit on top of those runtimes, compiler toolchains, GPGPU.

That infrastructure code is written in C++, and making use of Rust means adding yet another layer on how to compile, interop and debug, on top of what is already there.

As for safety in general, I am a believer of systems programming languages with automatic memory management, and polyglot programming, we aren't yet there because industry has the tendency to take decades to finally adopt good ideas, and only on a partial way.

Thus while I appreciate what Rust has achieved bringing affine types into mainstream, not an easy job, I consider this a transition step until we get both approaches in the same language, automatic resource management with affine,linear,effects,dependent types.

However this ultimately won't matter as much, when we eventually get our AI buddies good enough that they can spew executables directly.

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

#587
post #506

Earlier quoted context omitted.

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,…

I cannot follow your rant... I'll do my best to respond, but I'm probably not understanding something. Divide by zero must be undefined behavior in any performant language. On x86 you either have a if before running the divide (which of course in some cases the compiler can optimize out, but only if it can determine the value is not zero); or you the CPU will trap into the OS - different OSes handle this in different…

The problem is 'undefined behaviour' is far too powerful.

Why not make division by zero implementation defined. I'm happy with my compiler telling me my program will get terminated if I divide by zero, no problem. Let's even say it "may" be terminated (because maybe the division is optimised out if we don't actually need to calculate it, fine).

My problem is that UB let's compilers do all kinds of weird things, like assume if I write:

    int dividebyzero = 0;
    if(y == 0) { dividebyzero = 1; }
    z=x/y;
Then set dividebyzero to always be 0, because 'obviously' y can't be 0, because then I would invoke undefined behaviour.

Also, for two-complement, it's fairly common people want wrapping behaviour. Also, I don't think basically anyone is using C++ on non-twos complement CPUs (both gcc and clang don't support it), and even if it does run on such CPUs, why not still require a well-defined behaviour, in the same way C++ runs on 32-bit and 64-bit systems, but we don't say asking for the size of a pointer is undefined behaviour -- everyone just defines what it is on their system!

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

#588
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).

Kind of, compatible with C89 as language, and with C23 to the extent of library functions that can be written in that subset, or with C++ features.

And yes, being a "Typescript for C" born at the same place as UNIX and C, is both what fostered its adoption, among compiler and OS vendors, and also what brings some pains trying to herd cats to write safe code.

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

#589

Earlier quoted context omitted.

Honestly, I don't think libraries should ever panic. Just return an UnspecifiedError with some sort of string. I work daily with rust, but I wish no_std and an arbitrary no_panic would have better support.

Example docs for `foo() -> Result `: # Errors `foo` returns an error called `UnspecifiedError`, but this only happens when an anticipated bug in the implementation occurs. Since there are no known such bugs, this API never returns an error. If an error is ever returned, then that is proof that there is a bug in the implementation. This error should be rendered differently to end users to make it clear they've hit a b…

My main issue with panics is poor interop across FFI boundaries.

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

#590

Earlier quoted context omitted.

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.

I can tell that during 1999 - 2003, the aC compiler we had installed on our HP-UX 11 development servers, still had issues with C89, we had #defines to use K&R C function declarations when coding on that system.
Post reply on HN