Earlier quoted context omitted.
How about using an algebraic effect system? That's sort of a general purpose alternative to monads that also doesn't require an extra code path, and adds a bit of theoretical niceness. For example, if your code can throw two different exceptions, composing two monads is order-sensitive (because the monad interface is in some sense too general and forgets too much), while algebraic effects always commute with each oth…
True. I could rephrase as "the possibility of errors is just another type, and is best treated as such"?
Errors and Exceptions
41–50 of 55 posts
Re: Errors and Exceptions
#42Earlier quoted context omitted.
I think it's more a product of application complexity. The deeper the waters below you, the less you can meaningfully do with errors triggered by our actions. The closer you are to the hard boundary with the outside world, the more easily you can enumerate error conditions and be complete. A server connected to a network socket is very close to the wire protocol, and the potential error states are fairly well known a…
I like this distinction. It makes sense to me based on my experience, and as an extra bonus, explains the passion on both sides of the debate. If you don't have both kinds of experience, obviously one is strictly better than the other, it just varies as to which one that is. Both sides look at the other in horror and ask "Why are you trying to ruin my programs?", with good justification.
Higher up the stack, it's more likely you're dealing with an abstract object of some kind with no direct correspondence with the outside world. Exceptions are more likely to be an unexpected state, where unexpected means an unexplored area of the state space owing to an increased number of moving parts.
Re: Errors and Exceptions
#43First of all it seems that some people are still having a bit muddled vision about what is an exceptional error/condition. Of course you will need to first define what constitutes an exceptional situation in your application and its domain. The blog post used a file opening as an example. That example implied that in that software, in that particular context we have a requirement that our file must be opened. If for some reason it cannot be opened we have grounds for an exceptional condition. When we have this condition we then choose some particular method/means for how to indicate the situation and how to deal with it.
We can also demonstrate this the otherway around. Someone mentioned as an example something like a (web)server. Obviously in that application's domain not being able to open and serve some file is just a part of the normal flow. Clients may make request to resources that do not exist. So in that example that would not be an exceptional circustamce but the "FILE NOT FOUND" condition is just part of the normal conditional flow of the program.
However in that same server we might be for example reading the initial configuration file when the program is started and if we fail to open the file then we might have grounds for an exceptional situation.
So to sum this up, what constitutes an exception situtation is all up to the domain of the program. The blog post discussed methods for dealing with that situation. This is an important point to realize.
Finally a note on assert, yes there are cases when you can't hard fail and core dump on assert as much as you would like to. For example when implementing API's that define error return values for "hard failure" conditions. Whether this is sensible practice and makes the software world better or worse is a matter for another discussion.
Re: Errors and Exceptions
#44Earlier quoted context omitted.
How is that different to option 2?
It has nothing in common with 2. It's an extension of 4 where the eventual (dynamically scoped) handler is executed on the non-unwound stack and may unwind the stack (same as an exception), perform an action on the non-unwound system (e.g. resume, resume with a value provided, resume with a restart specified, repeat, etc…) or dynamically opt to resume looking up handlers.
Re: Errors and Exceptions
#45Re: Errors and Exceptions
#46Earlier quoted context omitted.
Strong type system with a good support of checked exceptions would tell you what kind of exceptions can arise from every function call. If you don't check them in your function code, they would add to the list of exceptions that your function can throw. It would basically turn every function you write with return type T into Either with syntax sugar that would transfer exceptions between calls so you don't have to sp…
With this scheme you would end up with pretty bad problems regarding function pointers and lambdas. Because the type is deeply implicit, you would have two function pointers that look compatible but are totally incompatible. Then when you want to assign them to a variable -- how do you know a priori what type to declare the variable?
Let's say we had the following C++ code:
int foo(int (*bar)(char), int (*baz)(), char c) {
try {
return bar(c)
} catch(SomeException &e) {
raise otherexception;
}
}
What exceptions can be raised by foo?The answer is simply computed - "anything raised by its first argument except SomeException, plus the type of otherexception".
Such a system would be tremendously more flexible than Java's checked exceptions, while still allowing you to confidently restrict what might be thrown in a section of code.
Re: Errors and Exceptions
#47Earlier quoted context omitted.
Go read one of Herb Sutter's "Exceptional C++" books. Okay, just read the first one. If you don't close the book and reflect, "I am never writing this shit," Herb didn't do his job. Writing exception-safe code in C++ is very hard. Depending on another module's authors to get their C++ exception handling right is the road to madness. In the example above, the FAILED clauses clearly handle all the failures. In the exce…
If you don't close the book and reflect, "I am never writing this shit," Herb didn't do his job. The same Herb who said Prefer to Use Exceptions to Report Errors ? (which makes no sense btw, just like saying to never ever use them) Depending on another module's authors to get their C++ exception handling right is the road to madness. Wait, so we should just forget about STL/boost/.. and reinvent all wheels? Or maybe…
Not weighing in on the broader discussion (in this comment), but more languages support exhaustiveness checking of case statements than of exceptions.
Re: Errors and Exceptions
#48Earlier quoted context omitted.
> Much of the trouble with error returns comes from the strange C convention that functions with return values can be called as if they didn't return a value. The "warn_unused_result" GCC function attribute makes the compiler emit a warning when you do `func(something);`: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attribute...
The problem is it needs to be applied to every function that returns a value. And I'm pretty sure you can't apply it to C library functions. Gcc seriously needs a global flag for this.
Re: Errors and Exceptions
#49Earlier quoted context omitted.
The problem is it needs to be applied to every function that returns a value. And I'm pretty sure you can't apply it to C library functions. Gcc seriously needs a global flag for this.
You might be surprised at the warnings you'd get. Did you know, for example, that printf returns a value? It's also a return value that rarely, if ever, tends to be useful.
int written = printf("Got here");
if (written != sizeof("Got here") - 1) {
written = fprintf(stderr, "Could not print my sacred message\n");
if (written != sizeof("Could not print my sacred message\n") - 1) {
exit(I_DONT_KNOW_WTF_IS_HAPENNING_HERE);
}
}Re: Errors and Exceptions
#50Earlier quoted context omitted.
You might be surprised at the warnings you'd get. Did you know, for example, that printf returns a value? It's also a return value that rarely, if ever, tends to be useful.
As a joke, in case you are really paranoic about error handling, you might end up with this :-) int written = printf("Got here"); if (written != sizeof("Got here") - 1) { written = fprintf(stderr, "Could not print my sacred message\n"); if (written != sizeof("Could not print my sacred message\n") - 1) { exit(I_DONT_KNOW_WTF_IS_HAPENNING_HERE); } }
You made a small mistake, since fprintf and printf call the same underlying code, the error handling should be either log the error in any way still available, and then depending on the design of the whole program, exit or continue. If printf fails you know exactly what is going on or have to exit. ( And printf would be wrapped in a function if you plan to use it repeatedly. )