top | item 46737396

(no title)

jpalepu33 | 1 month ago

The discussion around checked vs unchecked exceptions always comes down to ergonomics vs safety.

Having worked extensively with Node.js (callback hell, then Promises), I appreciate how error-as-value patterns force you to think about failure cases at every step. But the reality is most developers don't - they either:

1. Ignore the error case entirely (leading to silent failures) 2. Bubble everything up with generic error handling 3. Write defensive code that becomes unreadable

Rust's Result<T, E> with the ? operator found a sweet spot - you have to acknowledge errors exist, but the syntax doesn't make it painful. The key innovation is making the happy path concise while forcing acknowledgment of errors.

For Kotlin specifically, I'm curious how this interops with existing Java libraries that throw exceptions. That's always the challenge with these proposals - they work great in greenfield code but break down at library boundaries.

The real question: does this make developers write better error handling code, or just more verbose code? I'm cautiously optimistic.

discuss

order

HendrikHensen|1 month ago

The biggest problem is that people treat it as a dichotomy: either exceptions or error values. But that's a false dichotomy.

There would be real value in a language which would have both.

Error values are perfect for un-exceptional errors, e.g. some states of a business logic. The name that the user entered is invalid, some record is missing from the database, the user's country is not supported. Cases that are part of the business domain and that _must_ be handled, and therefore explicitly modeled.

Then there is the grey area of errors that one might expect (so not truly exceptional) but are not related to the business logic. These could be for example network timeouts, unexpected HTTP errors (like 503), etc. For those, there is often no explicit handling in the domain that makes sense. So it's convenient to just throw an exception, let it automatically "bubble" to the highest level (e.g. the HTTP controller) and just return some generic error (such as HTTP 500).

There are also truly exceptional cases, that you really shouldn't encounter in your program, such as null-dereferences, invalid array index access, division by zero, etc. These indicate a bug in the code (and might be introduced explicitly with assert-style checks). The program is in an unknown, compromised state, so there's really nothing left to do than throw an exception or panic. An error value makes very little sense in this case.

I often have the discussion with friends, why a division operator, or an array access, doesn't return a `Result` type in nice languages such as Rust? Surely, if they care about error values, then each operation that can fail, must return a `Result` rather than panic (throw an exception). It is an interesting through experiment at least.

josephg|1 month ago

> why a division operator, or an array access, doesn't return a `Result` type in nice languages such as Rust?

Rust has standard library functions to do this, if you want. arr.get(index) returns an Option. Integer types have .checked_div for panic-free divide. Float already doesn’t panic on an invalid division - it just returns NaN or Infinity.

frumplestlatz|1 month ago

It's absolutely a true dichotomy. If unchecked exceptions exist, all code must be carefully written to be exception-safe, and the compiler is not going to help you at all.

Of course it's convenient to be able to ignore error paths when you're writing code. It's also a lot less convenient when those error paths cause unexpected runtime failures and data corruption in production.

A preference for unchecked exceptions is one of my most basic litmus tests for whether a developer prioritizes thinking deeply about invariants and fully modeling system behavior. Those that don't, write buggy code.

Tyr42|1 month ago

Sounds like checked and unchecked exceptions.

I mean, this could be a syntax wrapper for java checked exceptions right?

Those are isomorphic to Result<_, Err> in that you must handle or propagate the error. The syntax is different, sure.

hackthemack|1 month ago

Similar thoughts.

One thing I notice in enterprise java software that I have to reed through and update, is that too many times, every developer just wraps everything in an exception. I do not have vast insight into all java code, everywhere, but in my little corner of the world, it sure looks like laziness when I have to dig through some ancient java code base.