Earlier quoted context omitted.
You are very confused... "strong" in strong typing doesn't mean you have to write much or at all. Actually, it doesn't mean anything really. But, let's say, Haskell is probably at least as "strongly typed" as Java -- at least that's how most people understand that wording. And you don't have to write types in Haskell at all. It will be a nightmare (as if Haskell can be anything else, but even by the very low Haskell…
> Until very recently, Java was just tedious, repetitive, high-entropy language, where you had to write everything multiple times. More than half a decade ago.
Why checked exceptions failed
241–250 of 318 posts
Re: Why checked exceptions failed
#242Checked exceptions failed because 99 times out of 100 the exception is not recoverable, so the try/catch block is just wasting everyone's time. (In 7 years as a Java dev I can think of one time I wrote code that tried to recover from IOException instead of just making the caller retry.) Even when the exceptions is theoretically recoverable, it has to get propagated up properly to the caller who should be handling rec…
The try/catch construct require too much code for the common propagate case.
It would be nice if Java had a similar construct for error handling.
Re: Why checked exceptions failed
#243Earlier quoted context omitted.
It's a very common pattern, almost every modern language has a "map" function. The map function can throw a superset of the exceptions that its argument can throw. If checked exceptions can't deal with this, they'll be of limited use.
> The map function can throw a superset of the exceptions that its argument can throw. Wait. Why should a map care about what exceptions it's arguments can throw? A map is storing a thingit. A thingit should exist independently before it gets placed into a map. Placing a thingit into a map should not invoke anything on the thingit. The only exceptions coming back from attempting to place a thingit into a map should b…
The map function takes a function and a list and applies the function to every element of the list:
map(double,[1,2,3]) = [2,4,6]
Grandparent could've used the for loop rather than the map function to make his point: for i in [1,2,3]:
print i * 2
-- because in general instead of the i * 2 we might have a call to a function that might raise an exception.ADDED. That is wrong: the for loop would not a good example at all because it is not customary to declare the type of a for loop or to need to declare which exceptions a `for` loop might throw.
Re: Why checked exceptions failed
#244Checked exceptions failed because 99 times out of 100 the exception is not recoverable, so the try/catch block is just wasting everyone's time. (In 7 years as a Java dev I can think of one time I wrote code that tried to recover from IOException instead of just making the caller retry.) Even when the exceptions is theoretically recoverable, it has to get propagated up properly to the caller who should be handling rec…
The argument that some exceptions will always be runtime (like oom) so checked exceptions are flawed is harder to argue against but I would also say it's a matter of opinion whether you feel like it's worth dropping entirely.
Re: Why checked exceptions failed
#245Re: Why checked exceptions failed
#246Earlier quoted context omitted.
No. This comes from a misunderstanding of checked exceptions. Checked exceptions don't mean I need to handle the exception right now. They mean I need to either do that or declare throws. Declaring throws is fine it implicitly documents the code and enforces a similar requirement up the chain. Checked exceptions aren't the default and shouldn't be.
Checked exceptions should be the default, exceptions should just be rare. They are overused in almost all languages.
The choice about where to handle the exception is almost always a good thing, since it reduces boilerplate in dealing with that condition. The cases where it's not a good thing are when it's either impossible to deal with the condition at all (e.g. assertion failure) or where it must obviously be handled locally (e.g. errno==EAGAIN type stuff).
The requirement to actually make the decision is a good thing in some cases (e.g. I/O), but not in other cases (e.g. out of memory) because the overhead of making this decision so often is larger than the benefit of avoiding that class of bug. It's beneficial when it's something that can only happen while doing certain well defined activities.
There are also places where there just shouldn't be an error at all. E.g. null pointers shouldn't be an error; your program should be rejected if the compiler can't prove that this is impossible through static analysis (even if that just forces the author to write assert(ptr!=0)).
I guess I'm converging on a scheme that looks like: I/O errors are checked exceptions. Out of memory is an unchecked exception. Assertion failures are panics which cannot be caught. Division by zero is prevented by static analysis. I'm not sure what should be done with EAGAIN/EWOULDBLOCK type stuff -- it doesn't really feel like those should be exceptions, but introducing a whole new "error" handling idiom just for this doesn't feel great either.
Re: Why checked exceptions failed
#247Checked exceptions failed because 99 times out of 100 the exception is not recoverable, so the try/catch block is just wasting everyone's time. (In 7 years as a Java dev I can think of one time I wrote code that tried to recover from IOException instead of just making the caller retry.) Even when the exceptions is theoretically recoverable, it has to get propagated up properly to the caller who should be handling rec…
I find the rust `?` construct nice for this: give me the success result or propagate the error. It is based on a result type though. The try/catch construct require too much code for the common propagate case. It would be nice if Java had a similar construct for error handling.
Still, it's too bad the error type must be a throwable. I kind of wish it could just be a plain type so you can error or cancel without generating stack traces. Awaiting a failed task could still throw.
Would be a nice perf boost. As it is now, you don't want to actually cancel or fail a C# task in performance critical code. You need to successfully complete the Task and return an error, which is pretty confusing.
Re: Why checked exceptions failed
#248Checked exceptions failed because 99 times out of 100 the exception is not recoverable, so the try/catch block is just wasting everyone's time. (In 7 years as a Java dev I can think of one time I wrote code that tried to recover from IOException instead of just making the caller retry.) Even when the exceptions is theoretically recoverable, it has to get propagated up properly to the caller who should be handling rec…
I find the rust `?` construct nice for this: give me the success result or propagate the error. It is based on a result type though. The try/catch construct require too much code for the common propagate case. It would be nice if Java had a similar construct for error handling.
Proliferation of types is an issue in Java, but the whole language has that problem. It's not just exceptions.
Re: Why checked exceptions failed
#249Earlier quoted context omitted.
> important failure that can't be dismissed But importance of the failure is determined completely by the program, not the library. Grep fails to open a file for reading -> message the user and exit Nuclear reactor controller fails to read important a file -> initiate reactor shutdown or something. If file read is critical, you have to handle failure no matter what the interface is. Because you know that disk can fai…
Grep fails to open a file for reading -> message the user and exit That should be: message the user and process the next file
Re: Why checked exceptions failed
#250Checked exceptions failed because 99 times out of 100 the exception is not recoverable, so the try/catch block is just wasting everyone's time. (In 7 years as a Java dev I can think of one time I wrote code that tried to recover from IOException instead of just making the caller retry.) Even when the exceptions is theoretically recoverable, it has to get propagated up properly to the caller who should be handling rec…
I keep returning to something about error handling that bothers me. People argue what the proper way to handle errors is without really considering that it's highly context sensitive. Which makes me think you should be able to pass an error handler down to lower level functions that tells them what to do when something bad happens. Sort of like recent ideas where you pass functions a allocator instead of them calling malloc() directly or whatever.