Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Exceptions were designed with the explicit goal of brushing potentially unrecoverable exceptional errors under the rug

That's what I meant by poorly reasoned arguments. Do you really think the designers of C++, Java, C#, Delphi etc all sat around and explicitly said to themselves "how can we brush errors under the rug"? Of course they didn't. They didn't even imply it, let alone state it explicitly, so that whole argument is just nonsense. They all argued, quite explicitly, that exceptions are a better way to handle errors than C style error codes. And their arguments were correct.

Using monad semantics to handle return types also provides a convenient way to implement what is often referred to as railway-orientrd programming

Again, this is what I mean by poorly reasoned arguments. "Railway oriented programming" is something FP languages made up to try and get closer to how imperative languages work, it's not something that's useful if you're already in an imperative language, exactly because exceptions already give you that and a lot more in addition.

Exceptions give the imperative programmer a lot of highly useful features:

1. Errors can be handled at the appropriate layer of the program, instead of all pieces of code having to be polluted with boilerplate propagation logic. Yes you have that problem even in FP languages. The right place to handle most errors is often at the outermost loop of your application or server, by logging it and discarding that unit of work or returning a description of the error to the user.

2. Exceptions come with stack traces and structured data about the error. I've often been able to fix bugs by just looking at the stack trace and nothing else. Error types usually don't have this information.

3. Exceptions can be abstracted without losing information, when chaining is used (as in Java). You can catch an error, rethrow it as a type appropriate for the abstraction level of your library, and do so without losing the original exception. Error types almost never have this kind of functionality.

4. Because exceptions are by definition exceptional, the compiler can safely assume those paths will rarely be taken and optimise accordingly. Error handling code can be moved entirely off the hot paths and out of the i-cache. Error types on the other hand are opaque to the compiler and result in branching everywhere, which hits performance.

5. When writing code that doesn't actually need to programmatically handle all possible errors e.g. prototypes, quick one-off tools you're writing for yourself, you can just let errors propagate to the top of your program and be handled automatically. You don't need to be constantly unwrapping Result/Either types, or propagating them, or handling them. You can just forget about it and still have useful diagnostics if something goes wrong. With error types, you either do the work by hand or you lose all insight into errors that doesn't make it into logs.

By all means, try and convince people that giving up all these features lets them "discretize and define the codomain of your function" and that this somehow substitutes for the pain of only using error types. It'll just make them slower than I am.



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

Search: