But for most example programs there's no easy way to handle errors further than just using expect() unless you want there to be more error handling code than actual useful example code.
The idea is that I expect this to be Ok/Some, and if it's not, please use this error message.
Here, the programmatic object is the grammatical object. That's what I meant by 'backwards'.
could_fail().or_panic_with('message') may be even better.
unwrap should be confined to test and temporary code. It somewhat makes sense in example code, but expect is better for that.
There are sometimes cases when you very easily know that the unwrap will never fail and if it does something has gone very horribly wrong, in which case you might use it.
Libraries should keep usage of unwrap/expect to a minimum. Applications can be more liberal with it, but they should try to use expect or better error handling.
Not everyone perfectly follows this, sadly. But most do.
This will print an error out already.
$ ./target/debug/tokiotest
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { repr: Os { code: 98, message: "Address already in use" } }', ../src/libcore/result.rs:837
Printing out a _better_ error might be helpful, though, I'll agree :) You could use expect for that, which lets you change the message in the ''s easily.This really shows a fundamental tension though, in documentation. Is this example supposed to be demonstrating error handling? Or just get you going? Does adding more complex error handling distract from the point it's trying to teach? These are sort of open-ended questions.
As I said in the post you're replying to, a nicer error message would be a good thing.
Whoever maintains the server and runs the service is also my user, though, in the general case.
> As I said in the post you're replying to, a nicer error message would be a good thing.
Yeah - I don't mind if unwrap panics with a dev-oriented message as it's basically an assertion, but I guess I expected expect() (no pun intended) to give a more user-friendly error. Maybe the format of the panic! output could be changed to bring the message to the front and the technical details after that.
Obviously not if it's used for input errors (network failure). Crashing assertions are made for bugs, not input errors.
We can agree in the cynical interpretation of the laziness of programmers, but the mitigations in this case are so trivial, and the stakes so low, that focusing on unwrap as a point of contention is a poor use of energy.
If rust had that examples would be even shorter using ? Instead of try! or unwrap
`quick_error` uses a trait like that to determine the exit code of `main()`, allowing it to return either () or i32.
quick_main!(|| -> Result<()> {
// insert Result-returning code here
});
Alternatively it takes a few lines to bootstrap it by hand e.g. ripgrep uses this code to bootstrap: fn main() {
match Args::parse().map(Arc::new).and_then(run) {
Ok(0) => process::exit(1),
Ok(_) => process::exit(0),
Err(err) => {
eprintln!("{}", err);
process::exit(1);
}
}
}
https://github.com/BurntSushi/ripgrep/blob/master/src/main.r...Such error handling code is usually untested, which is another way of saying 'buggy'. It almost always swallows useful information, like the backtrace. It sometimes lets program execution continue in a messed up state, causing very strange and hard to debug errors later on.
Certainly Rust makes it a lot harder to mess up error handling code than the languages I'm used to but in general I'm definitely in the 'all exceptions fatal' camp.
http://rust-lang.github.io/book/ch12-03-improving-error-hand... shows how to refactor a project to improve its error handling as well, for something a bit less abstract.