6 ms·
+1 for this! Unchecked exceptions subvert the type system, so they are convenient because they are cheating when compared with Result<T,E> types. Result<T,E>
by delhanty 10y ago
+1 for this!
Unchecked exceptions subvert the type system, so they are convenient because they are cheating when compared with Result<T,E> types.
Result<T,E> types are the one feature that have me thinking of moving from C++ to Rust. A lot of my experimental C++ code with callbacks looks like a bit like this now:
template <OnSuccess, OnFailure>
void someFunction(..., OnSuccess onSuccess, OnFailure onFailure)
{
...
Using the above style:
1. Allows error handling to be type-checked
2. Uses the heap less
But it's very clunky! If anybody has a better way to achieve these two things in C++ I'd like to know ...
Edit:
Erlang, which is known for its reliability, gets this right: kill the whole Erlang process in a clean fashion so that we can get transactional semantics. (It's not that performant though.)
- staticassertion 10y ago> Erlang, which is known for its reliability gets this right: kill the whole Erlang process in a clean fashion so that we can get transactional semantics. (It's not that performant though.) This is also the rust way - panics kill the thread they occur in.
- delhanty 10y agoThanks - that's good to know! Another reason for me to try rust then ...
- deleted 10y ago[deleted]
- fungos 10y agoJust for fun, really, I've done a Result impl in my lab code[1]. I'm willing to improve it just to see how far I can get with it. :) The next improvements will be custom error types (I had it done but reverted in this code) and a error_chain like feature (started testing and forgot to remove some not working code there). [1] https://github.com/fungos/sllab/blob/master/src/viewer.cpp#L43-L81 https://github.com/fungos/sllab/blob/master/src/viewer.cpp#L...
- delhanty 10y agoThanks for this. I don't fully understand your code yet: Is it the case that the type-safety of your approach relies on the caller honouring the convention of accessing Result<T,E> via the try and try_chain macros? I really need to look in detail at how Rust enforces type-safety of Result<T,E>. One thing that I like about how algebraic data types work in functional languages (e.g. Either in Haskell) is that they eliminate entirely the need for null pointers completely and the possibility of derefencing them (Tony Hoare's billion dollar mistake) and I had assumed that Rust would give me the same.
- steveklabnik 10y ago> I really need to look in detail at how Rust enforces type-safety of Result<T,E>. Basically, you can't use it as a T or an E; you have to process it in some way first. Basically, if you're familiar with Either, you know the whole story, it is the same. We originally had Either, then someone made Result, people always reached for Result over Either, so at some point, we axed Either. There is https://crates.io/crates/either https://crates.io/crates/either though too.
- fungos 10y agoThe type safety of my sample is based on the auto deduction of the types at compile time. You can see somewhere there I do this: return std::move(ArgsResult Ok(options)); I could also have done: ArgsResult func() { ... return Ok(options); } In this example there are two instantiations of the type Result<T, E>: typedef Result<ProgramOptions, Error> ArgsResult; typedef Result<bool, Error> ProgramResult; (Note that the typedefs aren't needed, but I prefer to be explicit there.) The try macro is just trying to emulate try! and it is not really needed. We may access the result by hand and the correct type will be used, but it is way uglier (see: https://github.com/fungos/sllab/blob/master/src/viewer.cpp#L269-L274 https://github.com/fungos/sllab/blob/master/src/viewer.cpp#L...) due the access on the struct members .e (error) or .v (value). And if I try to assign .v to another type, the compiler will give a compile time error. And probably would be better to use std::variant there as it is more like a tagged union, I just haven't tried to improve on it anymore. Also, note that my unwrap doesn't panic, I should put a test/assert there... Anyway, the poc is there and it should possible to have something almost as clean as Rust with some more work.
- sidlls 10y agoIt's fairly straightforward to have a rust-Result construct in C++. It's a bit more tedious if you want to make it a proper tagged union, but not inherently something that can't be done with a minimum of code and be as safe as possible.
- pixel_fcker 10y agoThere's this: https://github.com/ptal/expected https://github.com/ptal/expected which seems to work pretty well in my tests so far, though I haven't benchmarked it yet. The default implementation uses exceptions as the error type but you can supply your own type (e.g. an int, string, or a wrapped version of either or both) trivially.
- je42 10y agojust looked at this, nice! but i wasn't able to find how in the document how to propagate errors up the stack ? i.e. a parent function needs to expose an error type that is a base class of all errors that can occur the methods being called, right ? and i wondering how you would get stack traces from these errors ?
- pixel_fcker 10y agoBest just to use std::exception as the base class and derive from that, then if you want to get a stack trace just rethrow the contained exception. I've tried using this and my own implementation of Result<T,E> based on Alexandrescu's original talk, and both are significantly slower that C error codes or exceptions using the test program in the OP.
- delhanty 10y agoThanks for the link. I'll check it out and see whether it works for me.
- Ace17 10y agoIn case you haven't read it: The Trouble With Checked Exceptions ( http://www.artima.com/intv/handcuffs.html http://www.artima.com/intv/handcuffs.html )
- delhanty 10y agoThanks for the link. I hadn't read the interview, though I had read the following by Eric Lippert where he references it: https://ericlippert.com/2014/03/03/living-with-unchecked-exceptions/ https://ericlippert.com/2014/03/03/living-with-unchecked-exc... I'm not really a fan of checked exceptions either for the reasons that Anders Hejlsberg outlines in the interview. However, the bit where he writes: "I'm a strong believer that if you don't have anything right to say, or anything that moves the art forward, then you'd better just be completely silent and neutral, as opposed to trying to lay out a framework." Isn't that exactly what has happened with unchecked exceptions in C++ and C#? They've added complexity compared with C style error codes, without actually moving the art forward.