Hacker News new | ask | show | jobs
by weinzierl 1119 days ago
"And sure, plenty of people will tell if you do it "right" you'll have no issues."

My answer to that is always that if you are able to do it right in C or C++ (and maybe golang) you should not run into any issues with Rust. Especially you should not ever have to fight to borrow checker because it does the job you should be doing as a C/C++ programmer in your head anyway.

3 comments

The borrow checker rejects many otherwise valid programs. So if you do your job in correctly in C/C++, the borrow checker might accept the Rust equivalent or it might not.
Maybe that was true in 2017, but today borrow checker and compiler in general has covered so much of the Rust design space that the "correct programs" it rejects are more like rejecting Duff's Device kind of code. You are more likely to find yourself implementing low-level data structure or device interface where you need raw pointers tightly localized in the unsafe{} scope.
It rejects anything it can't prove. Sometimes that proof is trivial for the programmer. Consider a string table. You intern by passing an owned String, the string table sticks it in a HashMap and gives you back a &str with a lifetime matching the table. From a C/C++ perspective, that's fine; Rust doesn't know that you'll never be removing things from that table, but you certainly can (and encapsulation can help you enforce that).

Since 2017 it certainly admits quite a few more programs, but it's still pretty easy to find things that require a different approach than they would in C or C++.

The article says that this code doesn't compile in 2023. Assuming the intention was to print "fox", I don't see how it is incorrect:

  let mut animal = "fox".to_string();
  let mut capture_animal = || {
      animal.push_str("es");
  };
  //ERROR:cannot borrow `animal` as immutable because it is also borrowed as mutable
  println!("Outside closure: {animal}");
  capture_animal();
> Especially you should not ever have to fight to borrow checker because it does the job you should be doing as a C/C++ programmer in your head anyway.

It adds mental overhead.

I don't even like the "const" qualifier for functions in C++. It is so hard to get a design right upfront when thinking about non trivial 'const'-chains.

> It adds mental overhead.

The borrow checker removes the mental overhead of borrow-checking. You don't have to do it by yourself, you can lean on the borrow-checker to do that for you. In C++ you're all by yourself. You may pretend you don't need to do it, but you will run into troubles pretty fast.

Moving stuff into a closure is a perfect example of that. Try to capture an arcmutex to a bunch of threads in a closure? The compiler will note that arc can't be copied and to try moving it. It will then say you are trying to move the same arc to multiple threads, so you clone the arc. And if you try to just use an Rc it will tell you that can't be sent between threads (not thread safe) use arc instead. Those messages can absolutely guide you a long way before you realize your whole concept won't work, and that is frustrating, but those steps usually make you understand the whole issue.
"It adds mental overhead."

To me `const` removes mental overhead -- if I pass a const object somewhere, I can be sure it doesn't get changed. I don't need to inspect the code to make sure it doesn't call any methods that modify the object or trust a probably outdated comment or documentation.

When you are using the function, ye. Not when you are writing it. And if you someday want to change a const method to non-const you could have a cascading constness change all over the place.
But usually functions are used more than once.

"cascading constness change"

Which is good because invoking code may rely on function being read-only.

>"...it does the job you should be doing as a C/C++ programmer in your head anyway."

False. Too many false positives

"False" seems too strong. The job it does is track lifetimes. That's a job you should be doing anyway in C/C++.

It does so better than you can in that it doesn't have false negatives anywhere you're sufficiently playing by its rules.

You can also do so better than it can, in that you can see reasons things are okay that it can't understand.

I agree that there are too many false positives to assert that a competent C or C++ programmer doesn't have learning to do to appease (and leverage) the borrow checker.