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.
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?
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.
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.
http://www.ckwop.me.uk/Why-Exceptions-Suck.html
Not saying that this is the last word on exceptions, but these are the arguments.
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.
http://xach.com/rpw3/articles/0dudnfoyYfsNu8vanZ2dnUVZ_sKqnZ...
http://www.nhplace.com/kent/Papers/Condition-Handling-2001.h...
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
And Dylan has some material available as well:
http://opendylan.org/books/dpg/exceptions.html
http://opendylan.org/books/drm/Conditions_Background
http://opendylan.org/documentation/intro-dylan/conditions.ht...