Live data from Hacker News

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

collabora.com

561–570 of 675 posts

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

#561

Earlier quoted context omitted.

I don't speak for anyone else but I'm not using `unwrap` and `expect`. I understand the scenario you outlined but I've accepted it as a compromise and will `match` on a map's fetching function and will have an `Err` branch. I will fight against program aborts as hard as I possibly can. I don't mind boilerplate to be the price paid and will provide detailed error messages even in such obscure error branches. Again, sp…

So what do you do in the error branch if something like out-of-bounds index happens? Wrap and propagate the error to the caller?

Usually yes. But I lean much more to writing library-like code, I admit.

When I have to make a decision on an app-level, it becomes a different game though. I don't have a clear-and-cut answer for that.

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

#562

Earlier quoted context omitted.

> 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 This isn't really true since Rust has panics. It would be nice to have out-of-the-box support for a "no panics" subset of Rust, which would also make it easier to properly support linear (no auto-drop) types.

I do not want a library to panic though, I want to handle the error myself.

Let's say the library panics because there was an out-of-bounds array access on some internal (to that library) array due to a bug in their code. How will you handle this error yourself, and how is the library supposed to propagate it to you in the first place without unwinding?

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

#563
post #444
post #236

Earlier quoted context omitted.

Counterpoint: Decades of C++/Python/Java/... has strongly biased me against the try/except pattern. It's obviously subjective in many ways. However, what I dislike the most is that try/except hides the error path from me when I'm reading code. Decades of trying to figure out why that stacktrace is happening in production suddenly has given me a strong dislike for that path being hidden from me when I'm writing my cod…

There should be a way to have the function/method document what sort of stuff can go wrong, and what kinds of exceptions you can get out of it. It could be some kind of an exception check thing, where you would either have to make sure that you handle the error locally somehow, or propagate it upwards. Sadly programming is not ready for such ideas yet. --- I jest, but this is exactly what checked exceptions are for.…

Honestly I'm not even sure that Java checked exceptions are so bad in general compared to Result. The amount of verbiage is roughly the same.

Where Java failed is the inability to write generic code that uses checked exceptions - e.g. a higher-order function should be able to say, "I take argument f, and I might throw anything that f() throws, plus E1". But that, as you rightly point out, is a Java problem, not a checked exception problem. In fact, one of the more advanced proposals for lambda functions in Java tackled this exact issue (but unfortunately they went with a simpler proposal that didn't).

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

#564
post #507

Earlier quoted context omitted.

> 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.

Even then you're probably better off using something safer that transpiles to C.

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

#565
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?

Currying is just syntactic sugar for a lambda that binds the first argument and passes the rest unchanged, and you can achieve the same level of conciseness in other ways - e.g. "pipeline" operators - but with a syntax that is more readable and more extensible. E.g. https://docs.rs/piping/latest/piping/

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

#566
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 don't think currying is that big a deal, it's just syntactic sugar that might or might not make things easier to read, unlike ADTs or closures which are important core concepts. I'd love to have a syntax like { foo(%1, bar) } standing for |x| { foo(x, bar) } though. I'm not aware of any language that has this!

As noted in other comments, a bunch of languages has it, but the problem with this syntax is that it doesn't generalize well. For example, let's say we have:

   foo(%1, bar(%1, 42)) 
does this desugar to:

   |x| foo(x, |y| bar(y, 42)) 
or to:

   |x| foo(x, bar(x, 42)) 
and do you trust the person reading this code later to remember which one it is?

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

#567

Earlier quoted context omitted.

There are a few unit library in C++. Type checking in compile time is do-able with templates, even better with constexpr. The problem is, of course, each library have its own set of rules and they won't interop with each other.

I wrote such a type library myself, and it worked great. However we eventually realized it was the wrong answer because you so commonly want to display that thing and nobody wanted to write each widget to have a different api for each other the thousands of different types in my library. The current system is a runtime system which has one type, and you set what the unit system is in the constructor. However it means…

Er... why would you need a different API for this? Why not just convert to unitless at the point where the number flows into the UI?

Or better yet, parametrize the UI library so that it can display any unit automatically. It could even pull the metadata (like the string for the unit) from the template, so that e.g. binding a kg value to a label would automatically show as "42 kg" etc.

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

#568

Earlier quoted context omitted.

The question wasn't whether C/C++ are platonic ideals, the question was whether a language can be mature without a package manager.

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.

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

#569

Earlier quoted context omitted.

The C++ code I wrote 20 years ago also had strong typing and clear lifetimes. Modern C++ has reduced a lot of typing through type inference, but otherwise the language is still strongly typed and essentially the same.

The strong/weak distinction is a bit fuzzy, but reasonable people can have the opinion that C++ is, in fact, loosely/weakly typed. There are countless ways to bypass the type system, and there are implicit conversions everywhere. It _is_ statically typed, though, so it falls in a weird category of loosely _and_ statically typed languages.

I think that explicit casts really ought to be discounted, since if you're writing one, you are simply getting what you have asked for. This would be like saying that e.g. Modula-2 is weakly typed because it has bitcast.

That aside, the only remaining footgun in C++ is the implicit numeric conversions. What else did you have in mind?

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

#570
post #418

[flagged]

Undefined behavior can appear with or without templates. But other than that, yes, it is viscerally shocking to see on Compiler Explorer that your entire function has been compiled to a single instruction, ud2.

Seeing an entire function compiled down to a single ud2 instruction in Compiler Explorer was the moment I truly grasped the power of undefined behavior.

Templates are just tools — but undefined behavior (UB) is the real shadow lord. That seemingly innocent line of C++ code you wrote? The compiler might decide it has no meaning at all and emit ud2 — a deliberate “invalid operation” that crashes the program.

This isn’t just a language “gotcha”; it’s the compiler shouting: “Your code makes no sense to me — so I’m terminating it with prejudice.”

It’s both technically fascinating and philosophically unsettling. Who should bear the burden of balancing performance and safety? Should we be more careful developers, or should the language take more responsibility? Or… is this precisely the case for Rust?

The compiler didn’t betray you. It simply honored your undefined contract.

Post reply on HN