4 ms·
> the latest round of systems programming languages which all use error unions instead of exceptions have demonstrated quite clearly that exceptions are actuall
by dmitriid 4y ago
> the latest round of systems programming languages which all use error unions instead of exceptions have demonstrated quite clearly that exceptions are actually quite pointless.
What they have actually shown is that error unions are not a panacea and a pain to handle manually. And that hardcore killing your app in the presence of even the tiniest of unhandled errors isn't suitable for any programming, especially systems programming.
That's why Rust ended up introducing try!, ? and catching panics. Go also added panic recovery.
- zozbot234 4y agotry! and '?' is just a syntactic convenience for passing error returns to the caller. It's not even monad-like because the outer code still has to wrap the happy path return with Some(...) or Ok(...), which wouldn't be the case with an actual monad. (I.e. it's quite different from what was done with "async fn" support, where the Future return type is hidden via the 'async' specifier and the control flow is totally changed.)
- dmitriid 4y ago> try! and '?' is just a syntactic convenience for passing error returns to the caller. Indeed. Because manually handling those are a pain in the butt. So they made a shortcut. That still needs to be handled by someone up in the hierarchy. Exceptions in all but name. > It's not even monad-like because No one cares whether it's monads or not.
- moloch-hai 4y ago> Exceptions in all but name. But with added space and branch-predictor overhead in every call site, and runtime overhead in every call event!
- tialaramex 4y agoThe crucial thing about Try (the ? operator) is actually pretty easy to see if you look at the Trait which makes it go: The result of the branch method on Try is ControlFlow<Self::Residual, Self::Output> Try isn't stable, but ControlFlow is. They've reified the control flow! Rust has a type which represents the idea of a decision whether to return early. This is in my opinion pure genius, and it happened almost by accident. It seemed natural at first that the decision to return early is manifested directly in Result, but it isn't. That's the insight. Failure and returning early are distinct ideas, and we might just as easily want to return early in consequence of success as failure. In separating "Success versus Failure" from "Return early versus keep going" Rust gets a lot more value here than is encapsulated in C++ Exceptions.
- the_why_of_y 4y ago> Exceptions in all but name. In particular, checked exceptions. This is a very interesting article that discusses the isomorphism between checked exceptions and error return types, they ended up with checked exceptions where a function Foo that may throw must be invoked with "try Foo()" - very similar to Rust's ADT-based macro/syntax. https://joeduffyblog.com/2016/02/07/the-error-model/ https://joeduffyblog.com/2016/02/07/the-error-model/
- Yoric 4y agoI'd argue that they have demonstrated that: - unions are not a panacea and are a pain to handle manually, as you wrote; - but with a little syntactic sugar, they turn out to work really, really well, much better than C++-style exceptions. There's something to be said for OCaml-style exceptions, which are actually even closer to zero-cost, but I wouldn't call OCaml a systems programming language. Writing this as one of the persons who advocated for try! around the time of Rust 0.4 :)