7 ms·
I really hate the phrase "fighting". Calling it a fight doesn't do justice to the conversations you have with the borrow checker when you use Rust every day. Yo
by kaosjester 10y ago
I really hate the phrase "fighting". Calling it a fight doesn't do justice to the conversations you have with the borrow checker when you use Rust every day. You don't fight with the borrow checker, because there isn't a fight to win. It's far more elegant, more precise. It's fencing; you fence with the borrow checker, with ripostes and parries and well-aimed thrusts. And sometimes, you get to the end and you realize you lose anyway because the thing you were trying to do was fundamentally wrong. And it's okay, because it's just fencing, and you're a little wiser, a little better-honed, a little more practiced for your next bout.
- echelon 10y agoFor a Rust practitioner, there is no fight against the borrow checker. It's like saying a Java developer fights the type system. Is the borrow checker painful to grasp at first? A little. But the safety and assurance it gives you is immeasurable. Write enough Rust, and before long, you'll know when your code won't compile as written.
- madez 10y agoJust because something is worth the hazzle doesn't mean people do it. Of course, some people are willing to study and learn, but I think you also need to cater to those who are not if you want widespread adoption.
- AnimalMuppet 10y agoIf I understand correctly, the borrow checker is part of how Rust prevents dangerous code. Rust is not in the business of catering to those who want to write dangerous code, even if that means Rust will not achieve widespread adoption. There are already languages is wide use that allow writing dangerous code; for Rust to become another such language would not be a step forward.
- steveklabnik 10y agoRust does let you write dangerous code; it just makes you explicitly annotate it. As a systems language, Rust _must_ give you total control when you need it. It's just not the default.
- ansible 10y agoAs I understand it, the issues that people have with the borrow checker in Rust are the same ones they'd have in another language like C++. Only there, the language doesn't help you become aware of issues, like memory leaks or other use-after-free type bugs. If you really don't want a hassle, then maybe you want to program in a garbage-collected language instead. But then you're potentially giving up some performance and/or memory usage savings.
- steveklabnik 10y agoTo be clear, while this is true in the general case, there are specific moments where it does break down, due to the conservative nature of static analysis. This thread has some good examples, but in the interest of transparency, I'll provide another: struct Foo { s1: String, // some sort of String data s2: &str, // a slice of said String } What Rust doesn't understand here is that the String's data is on the heap, and therefore, its address is stable. So if you try to construct this, Rust won't let you, because it thinks that the borrow of s1 by s2 would be invalidated by the move. This is fixed by https://crates.io/crates/owning-ref https://crates.io/crates/owning-ref, but it'd be nice if it understood it by default. In general, these cases are small, but they can be annoying when you run into them. As I said downthread, I very rarely run into them personally, but some others seem to constantly. YMMV.
- rrobukef 10y agoIs this actually safe? What happens if you have ownership, then you can mutate the struct Foo like this: foo.s1 = "World" Which destroys the original heap data. Then s2 is a dangling reference. Since references cannot implement a drop method, you need a wrapping datastructure WITH reference counting, like you said.
- steveklabnik 10y ago> then you can mutate the struct Foo like this: You couldn't because it'd be immutably borrowed.
- mtanski 10y ago> It's like saying a Java developer fights the type system. Plenty of people have fought the type system in Java. Happens all the time with Generics and Type eraser. How many projects have work around for that Scala, Flink, etc... And it is a fight with the borrow checker because there a plenty valid and correct code fragments that the borrow checker rejects.
- steveklabnik 10y agoI've said in a few conference talks that I see it more like this: your compiler is a good friend who is telling you that you're about to do something stupid. Relying on your friends' advice is often a good idea. And sometimes your friends are wrong because you know things they want, so you do what you were doing anyway.
- noblethrasher 10y agoBeautifully written. I've not yet had the pleasure of using Rust, but you've described my experience of recapitulating ML-style functional programming in terms of the C# type system.
- the8472 10y agoThat might be true if the borrow checker were sufficiently advanced to always know better than you. But in reality it is overly conservative and you have to expend effort just to get things to work. When that happens it feels a lot more like fighting a war, a waste of resources that ideally would have been avoided. Of course this may improve in the future, but right now I would leave the rose-tinted glasses in the drawer.