Rust absolutely nails the error handling department.
Python style exceptions, pros:
- rapidly drop through layers when needed to get to a stable entry point
- easy to add errors deep in the stack
Cons:
- basically a limited GOTO, therefore side-effect, therefore not composable
- no way to know if what you are calling is gonna throw on you
Java pros:
- have to declare exception types, so at least you know what you are dealing with
Cons:
- you have to always declare exception types, which can be tedious
- same non-composable GOTO-lite behavior
- adding an exception deep in the stack is tricky
Go pros:
- errors are values, therefore typed and technically composable
- no surprises
Cons:
- tedious, verbose
- can't rapidly unwind unless you panic
- rarely composable in practice, requires manual unwrapping in most cases
- adding an exception deep in the stack is tricky
Rust Result pros:
- strongly, statically typed
- no surprises
- higly composable
- can map over it
- rapidly unwind in a composable way with ? operator
Cons:
- adding an exception deep in the stack is tricky (but often amenable to programmatic refactoring)
It's no wonder Rust is the SO most loved language 7 years running.
Python actually has a Result type library which I really like, but it's been hard selling my team, and you really need buy in. But I'd give it a swing.
https://pypi.org/project/result/