Live data from Hacker News

Switching from C++ to Rust

laplab.me

161–170 of 289 posts

Re: Switching from C++ to Rust

#161
> In C++, you can comfortably measure the size of error messages in kilobytes. Infinite scroll in the terminal emulator is an absolute must because oh boy does the compiler like printing text.

And you usually want the first line, because that's where the line number you actually want to go to is. Perhaps removing repetition and not printing lines of stdlib headers would help.

Re: Switching from C++ to Rust

#162

Earlier quoted context omitted.

The overhead is the same. Rust just takes care that you're doing it right, while C++ lets you shoot your foot off in this area.

I know this is an unpopular opinion but if you want to stick with C++, the solution to this, at least in my experience, is to stop doing things that let you shoot your foot off. C++ gives you every tool in the tool chest, and most of them are not safe. Stick to a safe subset and you've solved 90% of all those stereotypically C++ problems. I've got a pretty big C++ codebase for my hobby projects, sanded down, polished…

> The few times I run into memory corruption, a memory leak, a segfault, dereferencing a shit pointer, undefined behavior, and so on, its always, always because I'm doing something I shouldn't be doing. Like working with raw pointers or pointers to pointers to pointers, or traversing an array of bytes to do something there's already a library that does, or manually calling delete on something, or using reinterpret_cast, or using one of the many footguns C++ happily gives me.

You've never used an out-of-bounds index? Accidentally used an object that was on the stack beyond the function call? Let an integer overflow? The problem with C++ is that all of these things don't look like unsafe operations, and people end up making mistakes with them that are not obvious.

Re: Switching from C++ to Rust

#163

Earlier quoted context omitted.

What libraries have you found to use unwrap liberally?

The standard library is one example. Indexing into a vector unwraps, as do many other stdlib functions.

the docs[0] are clear:

> be careful: if you try to access an index which isn’t in the Vec, your software will panic!

> Use get() and get_mut() if you want to check whether the index is in the Vec.

In my experience, most people are using get() if the source of the index is untrusted

[0]: https://doc.rust-lang.org/std/vec/struct.Vec.html#indexing

Re: Switching from C++ to Rust

#164

Earlier quoted context omitted.

This is exactly what I think too. Sum types are so powerful, I feel a lot safer in Python + mypy with sum types (`from typing import Union`) than anything with C++ [1] even though C++ has a significantly more complex type system (it's type system is TC) and Python is as type-unsafe as a language can get. C++ made this odd choice as if any complex type system is better than a simple type system. When I was a younger s…

C++ has std::variant though?

… and boost::variant if you’re either using an old code base or want to use boost serialization.

Re: Switching from C++ to Rust

#165
post #19

Earlier quoted context omitted.

so, um, unions? i have to say that in many years of programming, i have almost never needed to use such types.

The C++ (or Java etc) way to do many of the kind of things people do with Rust pattern matching & sum types would be via OO subtyping polymorphism. e.g. classic visitor pattern, etc. Way more verbose and awkward, and scatters the logic all over the place. Enums + switch is the other, and far less powerful.

Or, for the case of errors, with exceptions, which happen to have their own very limited pattern matching syntax.

Re: Switching from C++ to Rust

#166

The author mentioned that Rust errors sometimes force you to restructure your code to satisfy the borrow checker. I’m curious whether anyone has some real-world before-and-after examples of this kind of change.

A very specific case on admittedly a toy project.

I was working on a card game simulator and I had a Vec of players. I needed to pull two players from that Vec and the first player would give a card to the second player. In my head I would grab both players via get_mut and then perform my operation. However, get_mut borrows the vec mutable and the compiler complained that I borrowed the Vec mutably two times.

It took me a bit to understand why the compiler complained, but then it clicked: It couldn't prove that get_mut wasn't returning the same item both times.

There were a few solutions. One was to borrow the first player, take a card, drop the &mut and then take the second player. At some point in the future I could use https://github.com/rust-lang/rust/issues/104642 to get_many_mut. I ended up with a pretty inefficient version of get_many_mut that fully traversed my iterator to get the two mut references (which works because traversing the iterator guarantees you won't see the same element twice) and it was fine for a collection of a half dozen players.

Anyway, there's a little example.

Anyway, it was a small thing but

Re: Switching from C++ to Rust

#167

[flagged]

> C++ has a very long history (over 50 years) and to say he's some expert matter on the subject after a mere 4 years of "professional experience" is quite baffling to me. It's understandable that you're baffled, especially given that the OP didn't claim to be an expert. The OP pretty clearly did not claim any authority, and instead went out of their way to clearly disclose not just the number of years of experience t…

> Man, what an absolute stinky pile of bullshit.

Now let's feed that as a prompt to DALL-E :-)

Re: Switching from C++ to Rust

#168

Earlier quoted context omitted.

This is exactly what I think too. Sum types are so powerful, I feel a lot safer in Python + mypy with sum types (`from typing import Union`) than anything with C++ [1] even though C++ has a significantly more complex type system (it's type system is TC) and Python is as type-unsafe as a language can get. C++ made this odd choice as if any complex type system is better than a simple type system. When I was a younger s…

C++ has std::variant though?

Yes, but:

- nobody uses it in the ecosystem. As outlined in the article, a lot of value of Option/Result is derived from their pervasiveness in the Rust ecosystem. C++ is far from this

- the ergonomics of it are terrible: no pattern matching, structural variants instead of named variants (yes you can emulate that with wrapper types but meh), lambda-oriented matching means you cannot as easily do things like early returns, statement-oriented language limits the usefulness anyway, lack of combinators, and for error handling specifically, lack of `?` operator

- performance is dubious. I had very steep and unexpected performance cliffs when lambda inlining started to fail for some reason. Having sum types be a language construct guarantees we're not relying on things like lambda optimisation here.

Re: Switching from C++ to Rust

#169

The author mentioned that Rust errors sometimes force you to restructure your code to satisfy the borrow checker. I’m curious whether anyone has some real-world before-and-after examples of this kind of change.

The most common example is when you accidentally start doing object-orientation, and are trying to get a value to hold a reference to another value when there's no point in doing so from an ownership perspective, just so that it can be part of `self` in the method. The more you try to preserve the model, the wackier the errors get, until one of them is literally unsolvable and you have to junk the object-oriented design entirely. Generally this happens a maximum of twice, because once you've learned it your reflexes change, but generally this happens to everyone who came from an object-oriented language.

Re: Switching from C++ to Rust

#170

The author mentioned that Rust errors sometimes force you to restructure your code to satisfy the borrow checker. I’m curious whether anyone has some real-world before-and-after examples of this kind of change.

Iirc in part 9 of this and the talk linked, Cantrill did that

http://dtrace.org/blogs/bmc/2018/09/18/falling-in-love-with-...

Basically he moves from his homegrown pointer chasing looking a lot like a doubly linked list to just using a hashmap and putting the key in his structs. As a naive first approach to satisfy the borrow checker, thinking he would sacrifice performance but at least the compiler would be happy.

Spoiler: it got faster. Far faster. To his surprise.

Post reply on HN