4 ms·
Exceptions make code harder to analyze because they implement non-local control flow. Your two example statements aren't really equivalent. `ErrorICanHandle` ma
by gmfawcett 6y ago
Exceptions make code harder to analyze because they implement non-local control flow. Your two example statements aren't really equivalent. `ErrorICanHandle` may be a kind of exception that the `someCall` function has no idea about whatsoever -- it could be an exception propagated from much farther down the call stack -- while your if statement assumes the error was explicitly returned from the function.
- simiones 6y agoIn an exception-based language, assuming all functions potentially throw, code like this: someCall() is equivalent to code in a language without exceptions that looks like this: err = someCall() if err { return err } (ignoring for a moment non-error returns, which don't change the point significantly) Having functions that are guaranteed not to throw / return errors doesn't significantly change this shape. So basically it's no more non-local than the code you'll end up writing with error codes, in most cases, any way. The only difference is implicit vs explicit. > `ErrorICanHandle` may be a kind of exception that the `someCall` function has no idea about whatsoever -- it could be an exception propagated from much farther down the call stack -- while your if statement assumes the error was explicitly returned from the function. someCall doesn't need to know about the meaning of the error in either case. It only needs to propagate any error it receives from any functions it calls (that it can't handle itself). Think about the function I wrote myself: did it need to know the precise type of err? Nope - it just needed to know that it implements some kind of Error interface (which may be as simple as being a negative number, like a POSIX error code). Edit to give a more complete example: extern void bar(); void foo() { bar() doOtherStuff() } void someCall() { foo() doMoreStuff() } void main() { try { someCall() doFinalStuff() } catch (BarSpecificException e) { doErrorStuff() } } Is equivalent to this code: extern err bar() err foo() { err = bar() if err { return err } err = doOtherStuff() if err { return err } } void someCall() { err = foo() if err { return err } err = doMoreStuff() if err { return err } } err main() { err = someCall() if err is BarSpecificException { err = doErrorStuff() if err { return err } } else if err { return err } err = doFinalStuff() if err is BarSpecificException { err = doErrorStuff() if err { return err } } else if err { return err } } If I ask you in the second piece of code what will be executed after the call to foo(), is it any easier to reply than in the first version? Personally, I don't believe so.