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

Error handling and propagation is one of those things I found the most irritating and struggled[1] with the most as I learned Rust, and to be honest, I'm still not sure I understand or like Rust's way. Decades of C++ and Python has strongly biased me towards the try/except pattern.

1: https://news.ycombinator.com/item?id=41543183




Counterpoint: Decades of C++/Python/Java/... has strongly biased me against the try/except pattern.

It's obviously subjective in many ways. However, what I dislike the most is that try/except hides the error path from me when I'm reading code. Decades of trying to figure out why that stacktrace is happening in production suddenly has given me a strong dislike for that path being hidden from me when I'm writing my code.


There should be a way to have the function/method document what sort of stuff can go wrong, and what kinds of exceptions you can get out of it.

It could be some kind of an exception check thing, where you would either have to make sure that you handle the error locally somehow, or propagate it upwards. Sadly programming is not ready for such ideas yet.

---

I jest, but this is exactly what checked exceptions are for. And the irony of stuff like Rust's use of `Result<T, E>` and similarly ML-ey stuff is that in practice they end up with what are essentially just checked exceptions, except with the error type information being somewhere else.

Of course, people might argue that checked exceptions suck because they've seen the way Java has handled them, but like... that's Java. And I'm sorry, but Java isn't the definition of how checked exceptions can work. But because of Java having "tainted" the idea, it's not explored any further, because we instead just assume that it's bad by construction and then end up doing the same thing anyway, only slightly different.


> There should be a way to have the function/method document what sort of stuff can go wrong, and what kinds of exceptions you can get out of it.

The key phrase you're looking for is "algebraic effect systems". Right now they're a pretty esoteric thing only really seen in PL research, but at one point so was most of the stuff we now take for granted in Rust. Maybe someday they'll make their way to mainstream languages in an ergonomic way.


I totally agree with you that Java checked exceptions suck. IME exceptions are far more ergonomic than Result.

Nim has a good take on exception tracking that's elegant, performant, and only on request (unlike Java's attempt).


Honestly I'm not even sure that Java checked exceptions are so bad in general compared to Result<T, E>. The amount of verbiage is roughly the same.

Where Java failed is the inability to write generic code that uses checked exceptions - e.g. a higher-order function should be able to say, "I take argument f, and I might throw anything that f() throws, plus E1". But that, as you rightly point out, is a Java problem, not a checked exception problem. In fact, one of the more advanced proposals for lambda functions in Java tackled this exact issue (but unfortunately they went with a simpler proposal that didn't).


I liked checked exceptions. I just think they were overused. Had a CS prof that summed up the optimal case like this:

Programmer's fault: runtime exception

Not programmer's fault: checked exception

Reading from a file but the disk fails? Not programmer's fault. IOException (checked). Missed a null somewhere? Programmer's fault. NullPointerException (unchecked).


Lack of parametrization meant that any interface that could be implemented in a way that could e.g. throw IOException had to declare it on its methods, even if only a single implementation out of several actually used it. And API clients then had to handle those exceptions even if they knew that they never use the interface implementation that could throw.

Or, alternatively, the interface wouldn't declare it as thrown, and then you couldn't implement it in terms of disk I/O without rewrapping everything into unchecked exceptions. A good example of that is java.util.Map, if you try to implement it on top of a file-based value store.


there are answers in the thread you linked that show how easy and clean the error handling can be.

it can look just like a more-efficient `except` clauses with all the safety, clarity, and convenience that enums provide.

Here's an example:

* Implementing an error type with enums: https://git.deuxfleurs.fr/Deuxfleurs/garage/src/branch/main/... * Which derives from a more general error type with even more helpful enums: https://git.deuxfleurs.fr/Deuxfleurs/garage/src/branch/main/... * then some straightforward handling of the error: https://git.deuxfleurs.fr/Deuxfleurs/garage/src/branch/main/...




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

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

Search: