8 ms·
Despite all modern trends to use return value rather than exception I still think that exceptions are vastly superior approach to error handling. For me the ide
by vbezhenar 6y ago
Despite all modern trends to use return value rather than exception I still think that exceptions are vastly superior approach to error handling. For me the ideal implementation is Java without checked exceptions. Rust's panics are similar to exceptions, so for me the ideal implementation should include some short syntax to allow converting from Result to result value and throw panic for errors, but also allow hierarchy of panics and try-catch handling of those panics (so it would throw some specific panic, not just common panic).
- FiberBundle 6y ago> the ideal implementation should include some short syntax to allow converting from Result to result value and throw panic for errors As far as I know rust implements that with the '?' syntax.
- masklinn 6y agoNo. `?` will short-circuit the Err case, possibly converting an error value, but it doesn't panic. `foo?` desugars to[-1]: match foo { Ok(v) => v, Err(e) => return From::from(e) } What "converts a Result into a value and panics on error" is Result::unwrap[0], or Result::expect[1] (for a custom panic message). [-1] as of rustc 1.46 anyway, I don't know how "try blocks" will effect `?`, though possibly the combination of "try blocks" and unwrap would make it easier to just panic an entire function: currently each Result site has to be unwrapped by hand whereas otherwise you could just `?` every site normally and unwrap the entire block I guess? [0] https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap https://doc.rust-lang.org/std/result/enum.Result.html#method... [1] https://doc.rust-lang.org/std/result/enum.Result.html#method.expect https://doc.rust-lang.org/std/result/enum.Result.html#method...
- masklinn 6y ago> Despite all modern trends to use return value rather than exception I still think that exceptions are vastly superior approach to error handling. Not providing any value judgement but… this seems completely irrelevant to the topic. Rust has long-settled on not exceptions, and they are largely incompatible with the language's stated goals and purpose. > Rust's panics are similar to exceptions Except for the part where their very existence is optional. > so for me the ideal implementation should include some short syntax to allow converting from Result to result value and throw panic for errors You mean like `Result::unwrap` which has existed since before Rust 1.0 was a thing? > but also allow hierarchy of panics and try-catch handling of those panics (so it would throw some specific panic, not just common panic). I don't want to be too forward about it, but that's a language which really has nothing whatsoever to do with Rust: the "hierarchy of panics" alone is completely disqualifying so… I see even less what that comment's doing in here.
- vbezhenar 6y ago> Not providing any value judgement but… this seems completely irrelevant to the topic. Rust has long-settled on not exceptions, and they are largely incompatible with the language's stated goals and purpose. I think that it's possible to build a bridge from Result to panics, thus allowing a developer to choose a particular style of error-handling. I don't understand why exceptions are incompatible with language stated goals. > Except for the part where their very existence is optional. But that's up to developer to decide, right? By default panics do work. If I want to call `abort()` on panic, I have to explicitly configure it. > You mean like `Result::unwrap` which has existed since before Rust 1.0 was a thing? Yes, but with improved panics (including hierarchy of panics, capturing stacktrace) and enhanced language syntax to better integrate that model into a language, rather than discouraging people from using it.
- steveklabnik 6y ago> But that's up to developer to decide, right? By default panics do work. If I want to call `abort()` on panic, I have to explicitly configure it. Yes and no. If you need either semantic, you need to specify it, so that when others use your code, they ensure they don't get something that's broken. They "work by default" in the sense that that's the default behavior, but people don't rely on it because unless you say you require it, they may use your code without them.
- vbezhenar 6y agoI guess, you're talking about library code. Libraries should use Result on their API boundaries, that's for sure. If library internals wants to use exceptions-panics, I think that language should allow it, because that's an implementation detail and compiler should allow modules with different panic configurations to co-exist (for example library can use unwinding panic, but as soon as it leaves library boundary, application will abort if it's configured to abort on panic). If it's not possible to implement in a sane way, then I'm OK with libraries forced to use Results as the only error-handling strategy, because I'm more concerned about program code.
- cies 6y agoI'm curious as to why you prefer (unchecked) exceptions over "all modern trends to use [the] return value" with sum types like Result (Either in Haskell). Personally I follow with the trend and feel strongly that the Result-type approach is superior over (unchecked) exceptions in most cases, since: (1) they are much easier to reason about for me as a programmer reading and writing code, as it (2) produces code with easier execution flow and (3) uses the type system to specifically+exhaustively communicate the possible outcomes. I say "in most cases", as I believe there are (probably) some behaviours that are easier to express using exceptions, but in practice I rarely run into such cases. And when I run into them, I might simply not be able to come up with the right abstraction using Result-types. I find the Rust/Kotlin trend of only allowing one exception (the panic), as to dictate the language users to use other means to communicate/express multiple outcomes of a call. Both languages --- by having sum types + pattern matching switch statements + exhaustivity checks on switches over sum types --- also provide means to express/handle multiple outcomes of a call, thus rendering the prevalent use of exceptions mostly irrelevant. The hierarchy of exceptions that you mention are to me something that goes against the nature of typing discipline: they subvert the typing system (in case of unchecked) or add a additional typing component (in case of checked) to express/handle multiple outcomes of a call.
- jcelerier 6y ago> they are much easier to reason about for me as a programmer reading and writing code, I would hate to have to reason about the 250 possible errors coming from every single library underneath my app, especially when the immense majority of those are better left to be solved by the user (e.g. file cannot be opened because the usb stick was removed, audio device unavailable because you are using a pro audio driver that locks to a single app, the GPU cannot be opened because I did a driver update and must reboot, etc etc). Monadic error handling is fine when you have a finite, predetermined set of "things that can go wrong" - e.g. you're writing a small input parser for a text field, either it parses or it does not. But imho this is a microscopic amount of cases compared to all the "random stuff that can go wrong" in the average GUI app. And as a GUI app user, I really really hate when the app tries to do what's best for me - autoreconnect, write to another file, change the settings automatically, whatever. Just gimme an error popup and let me decide. > produces code with easier execution flow In C++ using RAII objects for state makes that concern pretty much disappear imho. Save your state & rollback in a tiny type's ctor/dtor and you're good to go, whatever you do, things can throw and what you were doing will be rolled back. Not as good as hardware transactional memory, sure, but apparently not a lot of CPU engineers are able to make that one work yet... > (3) uses the type system to specifically+exhaustively communicate the possible outcomes. back to 1, this is what I really do not want. Just write the happy / known-to-the-programmer path and let what you don't know about bubble up to main() or the top of your event loop.