Hacker News new | past | comments | ask | show | jobs | submit login

"Exceptions are typically — and correctly — seen as a control structure". So much for those who say using exceptions for flow control is bad.

If they're important enough to be part of the language, somebody's going to use them... and common library functions will too. Exceptions aren't usually something you can boycott in a language ... and if you're going to have to use them, well, it's best to treat them as part of your program's logic, yes? Consider the many different errors Google handles and it's not always a dead failure... https://github.com/google/lmctfy/blob/master/util/task/codes... it's nice to be able to both return a value and an unambiguous exception state with automatic closure of resources (e.g. finally, or rewinding the stack...) such that you can safely retry without cleaning up after yourself. That's the goal here. Of course, Google's Go language avoids exceptions by using multiple return values, conventions and a defer statement... but then you can't easily put all your error handling code in any one place, can you, without restructuring your code? To each language its conventions, I suppose.

Without meaning any disrespect, this is a sort of naive perspective that comes about when you consider a language in isolation.

When you try to use exceptions, you'll quickly encounter the following:

1. Your C++ code may be called by C code that knows nothing of exceptions.

2. Exceptions have big implications for API design. See for example GOTW #8 http://www.gotw.ca/gotw/008.htm , which acknowledges that "some interfaces can't be implemented in an exception-safe manner."

3. try/catch/throw have performance impact. Compilers optimize for the no-exceptions-thrown case, and the practical cost of throwing an exception can be prohibitively high. Google "Zero-cost Exception" for more.

The net result is that proper exception handling is difficult to incorporate gracefully, and "exceptions are all fatal errors" is a very reasonable position. Last I checked, Firefox is compiled with -fno-exceptions, and this is how Cocoa frameworks work as well.

Goto is a control structure as well. Does not mean you should use it (with certain exceptions). Unlike exceptions though, you can use it in limited amount in your codebase. With exceptions it's either everywhere or nowhere.

Yeah, I'm just going to go ahead and disagree anyway. Not only are they a poor structure for flow control they are an inefficient and slow one too, as Andrei mentions in his 2012 talk on expected<T>, a talk which also nicely illustrates the shortcomings of using them for their intended purpose as error handling.

In fact exceptions as implemented in C++ has to be one of my last favourite things about the language. They are an all or nothing proposition and yet were put in half heated and unchecked. Many years later the result I see is some or most programs have a catch(...) at some high level. Something went wrong, who knows what, can't even set the debugger to break at exceptions because they're being thrown everywhere all the time for flow control.

C++ exceptions came from ML.

The original purpose in ML was definitely control flow. Or rather, controllable heuristic search in the context of a proof assistant. A heuristic could "give up" by raising an exception and a meta heuristic would then try something else or give up.

They worked well because memory handling is clean and automatic in ML and because proof assistants mainly work in their own little world with little to no I/O (apart from logging to a file/stdout/stderr).

> ...can't even set the debugger to break at exceptions because they're being thrown everywhere all the time for flow control.

Any C++ debugger worth using will allow you to break on certain exceptions and ignore others. Even gdb permits this: http://sourceware.org/gdb/onlinedocs/gdb/Set-Catchpoints.htm... Any decently designed C++ program will have a sane set of exception classes that will be easy to filter when debugging.

The heuristic is that if the case is more frequent than something like 1/1000 then you don't use exceptions in these languages (C++, Java, ...). As they are a lot cheaper in languages like ML, people there tend to use them more for early exits out of things like folds.

A simple example:

  let prod = List.fold_left (fun acc a -> acc * a) 1.0 xs

should not fold over the whole list if a factor is 0.0 so they tend to use exceptions for that (or delimited continuations)

Java doesn't really give you a choice though, because so many of the standard library classes have exceptions baked in. Any code you write related to file I/O for example will have to have either a "throws" or a "try/catch" on it, or else it won't even compile.

Checked exceptions are much closer to "error codes" than unchecked exceptions. Checked exceptions just loosen the constraint a bit and let you defer handling to anywhere the caller's remaining function scope (or explicitly continue the throw)

Won't be the first time that I think Stroustrup has made a serious error, and is compounding his error by not repudiating the feature.

Go read Sutter's _Exceptional C++_ or any of its follow-on books. It appears nearly impossible to write solid software when you allow exceptions into your set of control structures.

The best response to an exception is: Restart. Catch the exception in something like main(), take a dump or write some diagnostics, and restart your app. You'll have a system that is more reliable and of better quality than if you try to handle exceptions "correctly" in the face of non-exception-neutral code, 3rd party libraries that get things wrong, and your own bugs, which are going to be many, and deep, and subtle, and probably intractable.

C++ is used in many environments where "restart" is not a viable option.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact