4 ms·
I’m unconvinced. Just superficially, when trying to lock a mutex, WouldBlock isn’t a “mistake” at all. It’s simply the outcome of the operation. More generally
by amluto 4y ago
I’m unconvinced. Just superficially, when trying to lock a mutex, WouldBlock isn’t a “mistake” at all. It’s simply the outcome of the operation.
More generally, this post suggests that nuance is important, but nuance can be a lot more complex than this success/mistake/failure tristate. For example, consider an operation to INSERT into a database table with a unique constraint. A constraint violation might be a severe error indicating corruption in one context, but it might be a perfectly valid result indicating that an alternative path is needed in another context. An attempt to open a file that does not exist could be a serious error or just fine, but it’s not usually a situation where retrying makes sense.
There are certainly outcomes that are unambiguously hard errors: if the library itself is corrupted, it’s functions can fail hard. Or if the caller violated a precondition, a hard error is warranted. But interacting with anything external is fundamentally messy, and expressing the outcomes is hard.
- bacon_waffle 4y agoMy initial reaction was similar, and I totally agree that there's a lot of essential complexity in this area. At the same time, there might be room for an ergonomic improvement too. It seems like the `?` operator is maybe a little bit too nice - I find that, in practice, the step up in effort between: let x = some_function()?; versus let x = match some_function() { Ok(value) => value, Err(Error::ThatOneRetryableError) => { // Retry } err => return err }; ...sometimes is just a little bit too much to bother. Is there a pattern/macro/??? that makes this sort of thing a little nicer?
- tempodox 4y agoThere are no one-size-fits-all abstractions for these things. Where to handle an error and deciding what to do under which circumstances is uncomfortable detail work. But it needs to be done if you want reliable software.
- bacon_waffle 4y agoIf it's fair to say that the abstraction we're talking about is a semantic thing, rather than a syntactical thing, then I think we're in total agreement. Rust (as far as I know - I'm totally not an expert, nor a programming language person) makes handling the black-and-white cases really nice, but it would be nice if there were less friction for handling the in-between cases. I'm not sold on the solution requiring a 3-enum `Outcome` vs a 2-enum `Result`, but also feel that things could be better.