Live data from Hacker News

Why checked exceptions failed

borretti.me

301–310 of 318 posts

Re: Why checked exceptions failed

#301

Earlier quoted context omitted.

> FWIW, my take is that they are largely equivalent except for more or less syntactic support for the approach. Yeah, as with lambda calculus and turing machines, they are equivalent in capacity. > Are we comparing the same things? Adding exceptions to the method signature is pretty explicit to me too. Maybe, maybe not. IME the IDE support for exceptions is quite a bit worse than for returning results and such. > I d…

> I don't quite agree with that, as with encoding it in the type system conveys more intentionality than with exceptions, IMO. Sure, but why keep using exceptions then at all? I am fine with returning errors making them explicit, but I would avoid exceptions everywhere (Go-style).

Because of interop necessity, mostly (As with f# which has exceptions because .net and c#).

Re: Why checked exceptions failed

#302

Earlier quoted context omitted.

Type inferencing can get you in trouble quickly. Consider this code: var fireable = someMethod(); firable.fire(); The programmer intended this code to fire an employee. Let's say this code is in a military application, and another programmer modified the someMethod() function to return a missile. As long as the missile object has a fire() method this code will compile just fine... and do something the code didn't int…

This is a problem of dispatch. Not so much of type inference... The problem with dispatch says that if a method gets overloaded too much and too often, then programmers tend to make mistakes when they assume how the method they call will work. You should be insane if your program accidentally confuses people with missiles, but I understand that this is a stretch to amplify the point. What tends to happen in practice…

> the programmer can toggle the display of inferred types to qualify every expression

That's a terrible solution. Eyeballing is not as reliable as compiler doing a check. The language should provide a way for the programmer to express intent, and the compiler should do the check.

You can express intent more clearly when you say:

    Employee foo = someMethod();
as opposed to:

    var foo = someMethod();
A real-life example: I once helped a kid with her Python program to sort numbers. I looked at the code and the algorithm seemed correctly implemented, but the output was incorrect. The bug turned out to be that she hadn't called int() to convert the user input to integer, so all of the data passed through the entire program as strings, and got sorted as strings. There was nowhere in the code where the programmer could express intent that this is supposed to be integers. This sort of thing would never have happened in Java. Well, unless you misuse 'var'.

Re: Why checked exceptions failed

#303
post #213
post #58

Earlier quoted context omitted.

Something like String|NoAnswer|None doesn't sound too bad to me here...

Except that NoAnswer has none of the language’s (and it’s library’s) support for the built-in None. And you might run into problems when trying nest the data structure, which might be a reasonable thing for your users to do.

I just think that the nesting offered by Option & Co has overall much more downsides than upsides compared to union types.

Re: Why checked exceptions failed

#304

Earlier quoted context omitted.

In the case of map function hopefully you're using it with methods that don't fail in serious ways, and don't need strong error recovery. If so Java has RuntimeException to handle that case. If serious errors are possible and strong error recovery is needed, then you need to avoid the conveniences offered by functional style programming.

Sorry. This is nonsense. map() is the bread and butter of any program. Besides, you cannot ever decide whether an exception is important or not -- it's always in the purview of the user. Re-throwing a non-checked exception is what I described as the usual / typical coping mechanism in languages with checked exceptions. Which is obviously a way to negate the whole feature.

Sorry, disagree. map() didn't even exist in Java until recently. It is convenience at the cost of some safety. If you're writing a non-critical or throw away code you may not care about strong guarantees. Personally I prefer strong guarantees over convenience. I would only use map() for things that can't throw checked exceptions. A for loop isn't that hard to write.

Re: Why checked exceptions failed

#305
post #212

Earlier quoted context omitted.

But the point is that in both cases the failure needs to be handled somewhere and somehow. Surfacing the error might be a valid option, but to make the decision you need to know that the error is there in the first place. This can be solved with good documentation, but it can also be solved in the type system. Typically, if I can get my computer to do work for me (e.g. make sure that I've handled all possible error c…

Exceptions aren't normal parts of the type system though, they're a way to enforce control flow to deal with them. Another way to do this is with a Result type, which would actually be part of the same type system that you use in the rest of the language.

Why can't they be part of the type system? Rust is a good example of a case where they are part of the type system (albeit in a more monadic form). You've also got typed effects, where effects are essentially a generalised form of exception.

Re: Why checked exceptions failed

#306

Earlier quoted context omitted.

I'm curious how this is possible? Exception throwing and handling is fundamentally a flow control construct. ie: throwing an exception must control flow. A counter-example snippet where throwing an exception does not control flow would be appreciated.

An exception would be if someone tried to get the parking status for "Blarghsday" from the function or some other impossible state (We all know time is weird[0]) If the expected operation is to return parking allowed status for a specified date or a weekday, I'd expect the function to return true or false unless the input is malformed (Actually I'd prefer it to return some kind of object that can give more context to…

I'm afraid that this has left me more confused.

What's normal operation? It sounds rather subjective.

It sounds like there are those who "expect the unexpected" and those who don't, and this plays out in weird programming language usage discussions. Among all the expectations that one could have about a program, people have the impossible choice of being either complete and inconsistent or incomplete and consistent in their operational definition of "normal". Is it not?

Re: Why checked exceptions failed

#307
post #209

Earlier quoted context omitted.

Null pointer exceptions shouldn't exist in the first place, they're fairly trivial to avoid. Index out of bounds can be similarly avoided, although the cost in terms of economics is a lot steeper. I like Rust's strategy of providing a checked and an unchecked indexing mechanism, where the unchecked indexing mechanism typically crashes the program rather than just throwing an exception. Illegal arguments can often be…

Notice that parent comment was directed to a person who has the opinion of "everything should be a checked exception"... Not towards you. Crashing the program isn't an option for a lot of applications. All those exceptions give me a runtime stack that I can log and an error that's very easy to fix quickly. The first 3 are runtime exceptions which means you won't know about them and don't need to write defensive code.…

I think almost everything should be a checked exception, with some possible exceptions (haha) being things like out-of-memory exceptions (although even then, with a good type system, I can imagine them optionally throwing checked exceptions). So it's definitely written at me!

Rust is not the only language that handles these sorts of issues, and it's not the only way of doing that. OCaml also very neatly avoids most of these problems (again, indexing can optionally be checked), although it also includes exceptions on top of that. Even Typescript can be written in a style where exceptions, although interfacing with third-party code is a lot more difficult then. You can even configure the Typescript compiler to enforce checked indexing and prevent index-out-of-bounds errors.

The point is that there is nothing fundamental about these exceptions, other than that many languages have been designed with the assumption that they must be present and generally possible. But there's no reason to keep with that assumption, and we can write good code - and even good enterprise code, as demonstrated by Typescript - without those assumptions.

I find it disappointing that we expect so little from our tools that we tolerate these sorts of problems.

Re: Why checked exceptions failed

#308
post #195

Earlier quoted context omitted.

What do you mean when you say "exceptions should be rare"? Do you mean they should not occur frequently during runtime, or that it should be rare to see explicit exception handling in a piece of code?

Situations in which you must raise, propagate and handle exceptions should be rare.

Parsing input, handling I/O is a good chunk of what a lot of run of the mill software does. Since this is Java and exceptions are the main way of expressing fallibility, I’m at a loss as to what should code that needs to indicate fallibility should be using other than exceptions.

Re: Why checked exceptions failed

#309

Earlier quoted context omitted.

The problem with union types for exceptions is that it becomes impossible to return an error as the correct case, or at least there is no way to discriminate any more. Functions that deal with errors also need to be able to have exceptional situations, and in many cases there are completely generic functions as well that can error out for generic reasons. A basic example is the elementary case of having a list of err…

> And there's a good reason almost no statically typed language has support for union types For what it's worth, I learned about union types from Ceylon, which was statically typed.

Which is a very obscure language.

Type erasure at runtime simply isn't really possible with full union typing and looking at it as a consequence Ceylon has to box everything into a structure which contains a type tag which is obviously not an overhead a language such as Rust is willing to pay.

Re: Why checked exceptions failed

#310

Earlier quoted context omitted.

What about them? If your language semantics are pervaded by exceptions, that kinda suggests your language sucks. If you're unlucky enough to find yourself in this situation, then make exception contracts simple to express and propagate.

They aren't simple to express and propagate? What's so hard about declaring throws?

You have to think about exception polymorphism. If you don't have exception inference, you also have to think about manually propagating exception contracts. Declaring it once is not a big deal, doing it over and over again is super annoying.
Post reply on HN