Then you top it on with `?` shortcut and the functional interface of Result and suddenly error handling becomes fun and easy to deal with, rather than just "return false" with a "TODO: figure out error handling".
Then you top it on with `?` shortcut and the functional interface of Result and suddenly error handling becomes fun and easy to deal with, rather than just "return false" with a "TODO: figure out error handling".
I like rust, but its not as clean in practice, as you describe
type Result<T> = result::Result<T, MyError>;
#[derive(Debug)]
enum MyError {
IOError(String)
// ...
}
Your owned (i.e. not third-party) Error type is a sum type of error types that might be thrown by other libraries, with a newtype wrapper (`IOError`) on top.Then implement the `From` trait to map errors from third-party libraries to your own custom Error space:
impl From<io::Error> for MyError {
fn from(e: io::Error) -> MyError {
MyError::IOError(e.to_string())
}
}
Now you can convert any result into a single type that you control by transforming the errors: return sender
.write_all(msg.as_bytes())
.map_err(|e| e.into());
There is a little boilerplate and mapping between error spaces that is required but I don't find it that onerous.I would rather have what OCaml has: https://ocaml.org/docs/error-handling.
I actually find Zig quite a pleasant language other than my gripe with not handling more complex errors as cleanly.
Using out parameters for context, or diagnostic pattern like std does is not bad at all imo.
The only nice thing error payloads give you is better error messages in case of uncaught errors.