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.
I come from OOP languages and do rust mostly nowadays.
> you have to junk the object-oriented design entirely
I think it's not this black-and-white. OOP on a higher level is about encapsulation and message passing. Such design is perfectly doable in Rust. I'd say that it's more natural in Rust due to it's `impl` concept: where behaviour and data are coupled in a way that's different from most OOP languages.
Who owns which data, and who can operate on it, is something that, in OOP, should be thought about just as well. Java, Ruby, et al make it easy to make a mess from this; yet that doesn't make all OO-design a mess. Ihat really is "bad use of OOP", and no reason to "junk the OO design entirely". At most it's "junk the bad OO design".
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.
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.