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

For my own understanding, why do you say "(Exceptions) turn your program from a simple local thing into a complex nonlocal thing, which is not a good idea if you want to understand it well."?

My understanding exceptions only bubble up if they weren't handled at the point of failure. This is exactly the same if you don't check the return type of a function that could return error. Both of this situations point to poor programming technique rather than underlying implementation option.

One thing that makes me currently prefer exceptions to error returns is that within a try/with block you can write the code as you'd like to happen and hence easier to understand and maintain. All exception handling can happen within the respective catch blocks.

Because in order to know which instructions in your procedure might excecute, you need to know about the exception-handling behavior for everyone you call, which requires looking at the source code of everyone you call. User barkkel above in this thread was saying that passing around full return-value information for something like a file-open operation is somehow a violation of abstraction (this idea does not make sense to me) ... But I can't think of a bigger violation of abstraction than requiring you to know everything about everyone you ever call. Of course in reality people don't do this, which is then why programs that use exceptions have so many problems.

And if you say "why would you let exceptions bubble up that much", well, that is the whole point of exceptions, that they bubble up. If you say "to get rid of nonlocality just catch outside every call", well, now that's equivalent to checking return values always, but more error-prone.

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<T, ExceptionA, ExceptionC, ExceptionH> with syntax sugar that would transfer exceptions between calls so you don't have to spend your time with constant transfering of error properties of your return objects.

This would allow you to check stuff on places you desire (sometimes right after function, sometimes in the UI thread) and have tooling support for managing what is left unchecked.

Let's build something like that for C# using Roslyn! Issues of Java-style checked exceptions can be overcome using proper typing with generics.

In layered code, if not recoverable by the current layer, you should always encapsulate checked exceptions thrown by a lower layer - translated into an exception of the current layer (maybe generalized). This simple rule is often declared as overhead. I don't get that. I like code to be precise. The only situations where this gets complicated are those, where the rule is violated. And I think, the rejection of checked exceptions is often based on experiences with bad API design.

Exception handling must be trained and educated. There is no silver bullet.

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?

This would seem to be "just" a matter of correctly handling polymorphism along yet another axis.

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.

Good question. :-) I guess there definitely would be cases where the programmer would be restricted in what they want to do -- this is a nature of type systems. For example, I guess following code would not compile:

var f = (n) => n / 5; f = (n) => 5 / n;

What I hope for is that usual patterns would survive in a convenient manner. For example, calling function with function argument that is evaluated inside this function is something that could be handled by language without too many problems.

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