5 ms·
You do have a point, adding exceptions to C++ does impact the language in many ways. They must be used responsibly: being able to jump to a completely different
by tiniuclx 8y ago
You do have a point, adding exceptions to C++ does impact the language in many ways. They must be used responsibly: being able to jump to a completely different point of the program at any time is dangerous.
However, exceptions do simplify some situations, such as when an unrecoverable error happens at the bottom of a deep call stack. Exceptions make it simple to inform the user/system that an error has occurred without adding error checks to every function in the call stack. I believe this use-case justifies the feature, especially if you can tolerate the performance loss which might not even be that bad [0].
Having the compiler check error codes is one of the reasons I enjoy Haskell so much: the type system makes you handle failure (amongst other things).
[0] http://www.open-std.org/jtc1/sc22/wg21/docs/TR18015.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/TR18015.pdf - Section 5.4.1.2 - the table approach to exception handling has no run-time cost during normal (non-exceptional) program flow.
- jstimpfle 8y agoThe efficiency problem need not be the exception handling in itself (I can't say a lot about that. There are various claims and it probably depends on the tradeoffs of the language implementation). The actual problem is the ramifications on the code structure. A deep call stack with a lot of implicit context is a problem in itself. Exceptions imply a temporal coupling from error occurrence to error handling. This is a subtle but severe problem. It might start out as a noticeable maintainability problem but it's likely to quickly become a performance problem as well...
- uryga 8y ago> Exceptions imply a temporal coupling from error occurrence to error handling. Could you expand on this? I understood your statement as "Exceptions sort-of force you to handle an error the moment it occurs", but I'm having trouble seeing why this would be specific to exceptions and not the case with other error handling solutions. (I don't mean to sound like a big exception-defender – I prefer ML/Rust-style Result types)
- gbear605 8y agoA rather odd example with Result type systems: Say you have a function that returns the results of three other functions together in a tuple and the first one errors. The other two can still run and their result can be returned in the tuple along with an Error for the first function.
- uryga 8y agoAh, so using Result types you can return `(Optional<A>, Optional<B>, Optional<C>)` – each can fail or succeed independently. But you can't do that if you're using exceptions to signal errors – it's like returning `Optional<(A, B, C)>` , you get either all the results or nothing. Good example, thanks!
- Jtsummers 8y agoYou can still get something like that using exceptions, it depends on where the exceptions are caught. If you have a function which has 3 calls: function f (...) { val a = something.a(); val b = something.b(); val c = something.c(); return (a,b,c); } If the exceptions can occur in the calls assigning to a, b, or c and are handled locally (here, in f) then you can construct that first case. It's only if you throw the exception up one level higher that you end up in the latter case. As written, it is more like your latter example. But with a modication: function f(...) { val a = default_a; val b = default_b; val c = default_c; try { a = something.a(); } catch { a = error_value_a; } ... } You can get the former case.
- jstimpfle 8y agoIn some cases immediate action might have to be taken (like calling abort()) but very often that is not the case. Another strategy is to collect errors. Then decide what to do them at another point (no temporal or physical coupling!). After all errors are collected, you can group them, sort them, or aggregate them. Whatever is appropriate. Looking at errors as just data avoids the "exceptional vs non-exceptional" hair splitting, and gives a lot of flexibility for code structure. I don't necessarily disagree with the Result type viewpoint as a return type from functions, but I also find it pretty pointless. Very often the best action is to separate out errors from successes into different tables immediately. A built-in Result type couples them, and encourages keeping them coupled. Now you could argue that you can do that with Exceptions, too, by catching them immediately and treating them as data. In which case I want to ask "what's the point then?" and also refer to my topmost comment. Exceptions have a significant cost in infrastructure even if you don't actually use them...