You're placing a lot of trust in it not being undefined behavior.
Additionally, of course anything can be done with enough time and effort but the costs add up when you are doing things manually rather than letting the compiler handle it. Compiler has had many person-years of effort spent in ensuring the output is correct, can we do the same for all the code we write?
It helps because the instinct is to write lazy code that may fail and the rust compiler will annoy you until it compiles. Every annoyance to fix is a thing you usually need to think about in other languages.
For example, if I'm coding in C# it's easier for me to understand the impact of passing our resources that need to be disposed and good patterns to handle that after Rust has made me lose hairs on this concept.
This raises the question of whether that extreme paranoia prevents critical errors in code. The fact that so many of the issues still persist suggests it does not.
You can tell people to be careful drivers all you want, but what really saves lives is airbags, crumple zones, and seatbelts.
Because you can't let a driver crash and have a fatal accident as a lesson. That's what this is about. Make it hard and cumbersome, by having students build something non-trivial. I think another benefit of doing it is the Ikea effect, after you've put some effort into the project and see it come together, you might start caring about it and are motivated to get it to work well. Hopefully then some of that mindset carries over when using high level languages and huge frameworks.
> This raises the question of whether that extreme paranoia prevents critical errors in code. The fact that so many of the issues still persist suggests it does not.
> You can tell people to be careful drivers all you want, but what really saves lives is airbags, crumple zones, and seatbelts.
Could just be that the frequency of repeated accidents (and the related injuries) is too low to instill paranoia. The analogy is not the same as with programming in C, where the frequency is "multiple times a day", and not "less than once in a lifetime.
IOW, I feel that
> The fact that so many of the issues still persist suggests it [extreme paranoia] does not.
Back when every developer had to build their own failure detection code and display messages to help themselves debug anything that meant that almost every developer was good at communicating errors to the user.
Today developers don't build that skill, so you see applications that just fails silently everywhere or produce nonsense errors. The better developer tools you have the less your developers will need to learn UX skills to be able to do their work.
Agreed. And the example of crashing due to a NULL file descriptor is in the minority. Often C error handling involves checking errno. This is routinely ignored, and when some call "fails", the code continues to some point later where things don't quite work right. When this happens, it's usually much harder to determine the cause, given that the root failure context is gone.
I'm my experience, C developers sometimes just dislike exceptions in other languages because exceptions defy C code path expectations. That was my first instinct when going from C to other languages. And so additional arguments against exceptions are put forth, including performance issues (which are real) and this idea of paranoia being better than language tooling (which is rather suspect imo).
> And so additional arguments against exceptions are put forth, including performance issues (which are real) and this idea of paranoia being better than language tooling (which is rather suspect imo).
I feel you are mischaracterising my position, which was to have graduating students work in C for a non-trivial amount of time before they moved on to a new language.
The argument that paranoia is better than language tooling is entirely absent from my arguments.
It will compile just fine if you call unwrap on a Result and then you get a wonderful error. If you call unwrap on a File::open() you do not even get the file name.
If you run this
use std::fs::File;
pub fn main() {
let fp = File::open("test").unwrap();
}
You get this:
thread 'main' panicked at /app/example.rs:11:33:
called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
The language incentives you to propagate errors up to main and then just let it fail.
You still have to explicitly do this and are made aware of this failure state. It's also much easier to reject PRs when you see an unwrap than to try to think of all the ways it could invisibly fail.
How is that better for developing a sense of paranoia around error states?
"Throw it at the wall and see what sticks" does not exactly lead to "extreme paranoia managing errors".