When evaluating a LazySeq, if an exception occurs it gets wrapped in a RuntimeException and is thrown. Unfortunately, the logic does not differentiate between a RuntimeException and a checked exception. This has what I believe are two unintended side effects.
- If a function throws a RuntimeException, such as an IllegalArgumentException, it gets wrapped in a RuntimeException unnecessarily. So, if I am expecting an IllegalArgumentException (as in a test), I will unexpectedly get a RuntimeException instead.
- When evaluating nested lazy sequences, if an error occurs, the root exception is wrapped over and over again as the exception winds its way up the stack. In a recent project, this meant having extremely long stack traces that include a half dozen nested RuntimeExceptions. These just get in the way of getting to the root cause.
Both of these scenarios are illustrated in the attached file.
My proposed solution is fairly simple: Instead of indiscriminately wrapping every exceptions a RuntimeException, simply rethrow any RuntimeException. As a result, any RuntimeException will simply wind its way back up the stack with no wrapping, and checked exceptions will only be wrapped once. This should make debugging Clojure programs slightly easier as the resulting stack trace will not include as much irrelevant information.