4 ms·
> Argument by meaningless blither. What distinguishes > “exceptional conditions” from “control flow”? I have > reached the end of a million element list
by h2s 14y ago
> Argument by meaningless blither. What distinguishes
> “exceptional conditions” from “control flow”? I have
> reached the end of a million element list. This
> happens one time in a million! That sounds pretty
> exceptional to me!
Unless you were expecting the list to have infinite length, then this would be a misuse of exceptions. The true logical fallacy here is the author of this post's argument from personal incredulity. The fact that he hasn't yet learned how to distinguish between exceptional conditions and control flow doesn't mean that it's an impossible or meaningless distinction.
- DRMacIver 14y agoDo feel free to enlighten me.
- h2s 14y agoExceptions exist so that you can treat error handling as a separate concern and thus deal with it in a different area of the code. For example, you might have a REST API which catches authorisation exceptions and validation exceptions from the libraries it calls and turns them into appropriate HTTP 30* or 40* error codes, with runtime or null pointer exceptions instead becoming 500 Internal Server Errors. An example of misusing exceptions for control flow in this context would be throwing a "caching exception" to indicate that a cached version of the requested resource has been found and is to be returned to the client without any further processing.
- perlgeek 14y agoBy saying "Exceptions exist so that you can treat error handling as a separate concern" you are again putting the conclusion first. Maybe exceptions were invented for handling errors, but now that we have them, what's a good reason not to use them for other purposes?
- h2s 14y agoBecause using exceptions as control flow introduces a very awkward and strange type of coupling between components: dependence by one component on the presence of another known component higher up in the call stack. Dependencies between components should ideally be as explicit and as few as possible. Dependency injection is one good way of achieving this, but even global variables or singletons are more clearly self-documenting than exceptions. A piece of code that returns a value or makes a call to some functionality in another piece of code is easy to understand. If instead, that code throws an exception, then it sends the reader on a voyage of discovery throughout the codebase to investigate all the places that catch this type of exception, and which of those pieces of code can ever potentially be higher in the call stack than the piece that throws it. The only reason we even put up with such complexity in the case of handling errors is that it is the one problem that is ubiquitous to every piece of software ever written and therefore merits its own first-class language support.
- andyjpb 14y agoThrowing exceptions across API and module boundaries is a separate discussion which has separate pros and cons. When you define an API in a language that has exceptions you should be careful to define the behaviour around how exceptions are used. This is similar to how, when you define an API in a language that has threads, you should be careful to define your reentrancy and thread-safety guarantees.
- perlgeek 14y agoSo you wouldn't object to it if catching and throwing happens in the same component (however you define component)?
- h2s 14y agoTo truly minimise the potential for confusion with this approach, you'd need to be throwing and catching within the same method. And if you're doing that, you might as well just come out of the closet and use goto.
- 14y ago
- btipling 14y agoSo exceptions are about where in a file your code is? You can put your code anywhere with functions and modules, packages whatever.
- mcherm 14y ago> Exceptions exist so that [...] Are you talking about a language that you (h2s) wrote? Or some other language like Java, Python, C#, Ruby, CLU or PL/I? Because I doubt that you KNOW the reason that exceptions were made a part of the language. And it doesn't matter anyway. Imagine someone saying "the print statement exists so programs can output simple debugging statements to the console". It is mostly true, in the same sense that your claim about exceptions is true: that's the most common use for the print statement. But if someone writes a simple unix utility that reads from stdin and writes to stdout and they use the print statement to produce the output, would they be wrong? Or would they be using a language feature in a perfectly reasonable way which was understandable (once you knew about it) and had no performance problems? Imagine someone saying "the + and * operators exist to perform addition and multiplication on integers". It is mostly true, that's the most common use for these operators. But if someone wrote a bitset class and implemented some of the features using + and * operators, would they be wrong? Or would they be using a mathematical feature in a perfectly reasonable way which was confusing to people who have never done bit-level manipulation (unless they included clear comments) and had excellent performance? What I'm trying to say is that I'll listen if you argue "It is confusing to the reader for the following reason...". I will listen if you argue "It has the following performance issues...". I will listen if you claim "It can be incorrect in the following corner cases...". But when you say "It is bad because you are not intended to do it..." I will scoff and wonder who you think makes these rules.
- BruceM 14y agoYou'd probably enjoy reading about condition systems such as can be found in languages like Common Lisp and Dylan: http://xach.com/rpw3/articles/0dudnfoyYfsNu8vanZ2dnUVZ_sKqnZ2d@speakeasy.net.html http://xach.com/rpw3/articles/0dudnfoyYfsNu8vanZ2dnUVZ_sKqnZ... http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html http://www.nhplace.com/kent/Papers/Condition-Handling-2001.h... http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg02719.html http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/m... An early version of the Dylan manual had a good chapter on this subject: http://jim.studt.net/dirm/interim-66.html http://jim.studt.net/dirm/interim-66.html And Dylan has some material available as well: http://opendylan.org/books/dpg/exceptions.html http://opendylan.org/books/dpg/exceptions.html http://opendylan.org/books/drm/Conditions_Background http://opendylan.org/books/drm/Conditions_Background http://opendylan.org/documentation/intro-dylan/conditions.html http://opendylan.org/documentation/intro-dylan/conditions.ht...
- DRMacIver 14y agoSo it's legitimate to use exceptions to terminate early with an HTTP status code such as 304, but it's not legitimate to use exceptions to terminate early to say that there's a cached version of the page available and no further processing is needed. Have I got that right?
- h2s 14y agoIt was a dumb mistake on my part to mention the 300 range of HTTP status codes.
- andyjpb 14y agoh2s: Can you explain to us what exactly is the difference between the implementation of flow control during exception throwing and all the other kinds of flow control (including, but not limited to, stack popping).
- eps 14y agoDo you mind clarifying who is these "us" you are referring to?
- gleamer 14y agoExceptions, as implemented in languages such as C++, also influence the flow of execution. Therefore, technically, exceptions are a kind of control flow structure. But it doesn't mean that abusing exceptions as control structures is a reasonable idea.
- astrobe_ 14y agoIIRC no standard flow-control construct can do non-local returns (and that's where the Evil lies).
- andyjpb 14y agoHow about call/cc and setjmp/longjmp ?
- emn13 14y agoAnd those control flow methods are also widely considered to be tricky and cause a maintenance burden.
- shurcooL 14y agoJust making an observation here. The reason they are tricky and cause a maintenance burden is because they create non-obvious dependencies. You'd have to read a lot of seemingly unrelated code to spot them. Without the explicit knowledge of these dependencies, your changes will have unexpected consequences. (Hence, in a system that tracks all dependencies perfectly, this might not be a problem. This is an experiment I'm trying to run right now.)
- Raphael_Amiard 14y agoThe author is consciously using exceptional with another accepted meaning of the word (rare). And you are (consciously or not) at the same time misunderstanding him and being condescending, while adding strictly nothing to the discussion.
- dcminter 14y agoExceptions are often used to catch unanticipated situations but they are also, legitimately, used to simplify common case logic by moving special case logic elsewhere. "Exceptional" and "unanticipated" are not synonymous. Edit: I would add that it is true that there is a semantic burden with exceptions in that they are suggestive of error, rather than special case, conditions. So I would be very wary of using them in that way simply in my own code because it will potentially be misleading to consumers of the source code. But if the clarity of the remaining code is sufficiently enhanced then it's a fair trade-off.
- Chris_Newton 14y agoI would add that it is true that there is a semantic burden with exceptions in that they are suggestive of error, rather than special case, conditions. That depends very much on the idioms and conventions of whichever language you’re using. In Python, for example, there are some built-in exceptions like StopIteration that are used for routine flow control and do not in general represent an error.