Rob Elliot
09/14/2021, 9:09 AMfun <T, R> T.runCatching(block: T.() -> R): Result<R>
- it catches Throwable
, and hence Error
, including things you almost certainly don’t want to catch like OutOfMemoryError
. It also makes no attempt to propagate InterruptedException
(or reset the interrupted status of the Thread when catching it).
Am I missing something? Or just woefully out of date in my JVM exception handling?edrd
09/14/2021, 1:34 PMOliver.O
09/14/2021, 1:34 PMResult
, expecting its caller to examine that for failures and respond accordingly. What else were you expecting?christophsturm
09/14/2021, 1:59 PMchristophsturm
09/14/2021, 2:00 PMRob Elliot
09/14/2021, 2:05 PMError
is intended to represent all the things you should, as a general rule, never catch because they represent things you can’t sensibly handle. As a general rule they should hit the top, and halt the program or thread.
(Of course there are cases where you want to catch them, but they are very much the exception (see what I did there?) rather than the rule.)
In addition, from my reading of JCIP catching InterruptedException
accidentally by virtue of catching Throwable
or Exception
is dangerous because you should reset the interrupted status of the thread when you do so, otherwise interruption based cancel semantics don’t work. So it’s generally better to propagate InterruptedException
- unless you were catching it deliberately you probably don’t want to accidentally undo interruption. (On which basis InterruptedException
should really be a third direct subtype of Throwable
rather than a subtype of Exception
, but that ship sailed 25+ years ago.)
My assumption was that 99.999% of the time someone using runCatching
is not checking the result for Errors and rethrowing them, nor for InterruptedException & handling it appropriately, but is looking to bridge “control flow” exception throwing code into return value style code. In which case if I’m right about the above they shouldn’t actually want to use runCatching
.christophsturm
09/14/2021, 2:06 PMRob Elliot
09/14/2021, 2:07 PMtailrec
inside a try/catch
block, which was my immediate reason for turning it into a Result
& using when
on it.Oliver.O
09/14/2021, 5:28 PMrunCatching
without exhaustively handling its failures and re-throwing everything that can't be handled. I'd say, having a form of runCatching
which tries to single out specific failures by throwing and passes others would just be a pseudo-solution: Important failure modes might still be silently ignored by the caller. When there's no discipline and a very good use case, it's better not to consider using it at all.raulraja
09/14/2021, 6:48 PMchristophsturm
09/15/2021, 3:48 PMilya.gorbunov
09/15/2021, 4:17 PMResult<T>.rethrowFatal()
, analyze there if an exception is fatal according to your criteria and rethrow it immediately.