4 ms·
> in most cases I have no idea how to recover from error: just keep throwing it to the caller until someone knows what to do. I want it to be the default behav
by hota_mazi 6y ago
> in most cases I have no idea how to recover from error: just keep throwing it to the caller until someone knows what to do. I want it to be the default behavior and I don't want to clutter my code with all the catch-wrap-rethrow boilerplate.
What's your alternative? Using return values? But then you are doing the bubbling, manually.
Exceptions offer a more elegant and less boiler plate approach to this problem: if your code can't handle an exception, just declare it in your signature and ignore it. This is really the best approach to this problem:
- The error cases are part of the function's signature (as they should).
- The language takes care of bringing the exception to the right handler.
- Your code can proceed with the assumption that all the values are sound.
- aeternum 6y agoI've found that in practice it leads to very generic exception names. When a new failure mode is found for a lowlevel component, in other languages devs would add a new specific exception and things would generally work. In Java, devs have to modify every intermediate component to handle or pass the new exception type so they end up just using an existing one that is super generic.
- 0xffff2 6y ago>What's your alternative? Using return values? But then you are doing the bubbling, manually. Huh? The alternative is unchecked exceptions, which are already present in Java and therefore have to be accounted for anyway. Removing checked exceptions from Java would greatly simplify the APIs that use them, with absolutely zero cost.
- sreque 6y agoReturn values are a million times better than checked exceptions because return values compose and return values don't collide with the rest of the langugage. Checked exceptions are basically monads but with all the disadvantages of monads but none of the advantages. There is a reason no language since has copied them.
- ragnese 6y agoExcept that many languages just do worse. Go, Kotlin, Clojure (very different philosophy, though), C#...
- sreque 6y agoIMO the solution is to either: * Use return values and let people deal with the boilerplate ala Optional in java. We use Optionals to replace null values and IMO the boilerplate is 100% worth it. I've also used return values that can encode possible errors in Java. * Use unchecked exceptions and expect people to understand the methods they call and the exceptions those methods can throw, which should be documented in javadoc instead of a throws clause. This needs to happen regardless, as methods can throws unchecked exceptions the caller might need to be aware of, so this in reality doesn't involve extra work. For me, either of these solutions is preferrable to checked exceptions.
- ragnese 6y agoAgreed that the boilerplate of Optional is worth it. That doesn't mean it's actually good. With Java it's just a choice between "bad" and "worse".
- hota_mazi 6y ago> Return values are a million times better than checked exceptions because return values compose No they don't, not even when they're monads (you need monad transformers to compose monads since they don't universally compose).
- a1369209993 6y agoTechnically you only need swap (eg: swap :: Either e2 (Either e1 a) -> Either e1 (Either e2 a) swap (Left z) = (Right (Left z)) swap (Right (Left y)) = (Left y) swap (Right (Right x)) = (Right (Right x)) ) to implement join (at the functor `Either e1 . Either e2`) and then a general monad-compose. You could also use: join :: f1 (f2 (f1 (f2 a))) -> f1 (f2 a) -- join = fmap join . join . fmap swap -- if you have swap directly, which doesn't even require f1 and f2 to be monads in the first place (though they do need to be applicative for return/pure/unit). (See http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf for technical details.) swap is generally trivial (see above) for any sane error-reporting monad, although might be a bit more difficult if you're shoving error-handling logic into them.