Looking at the internal implementation definitely helps a lot too, but if you want the TL;DR: when you
raise()
, a
RaiseCancellationException
(usually the
NoTrace
version of it because it's more efficient) is thrown, and inside it contains your
Raise
instance, and the value you raised. Then, every
fold
block (which all raise builders ultimately call) will end up identity-checking that
RaiseCancellationException.raise === expectedRaiseInstance
. If that's true, then it casts the value to the expected type, and it's passed to the
recover: (Error) -> R
lambda that
fold
accepts.
It all boils down to
myRaise.raise(errorVal) == throw RaiseCancellationException(myRaise, errorVal)
and
fold == try { block(myRaise) } catch(e: CancellationException) { recover(e.raisedOrRethrow(myRaise)) }
where
e.raisedOrRethrow(myRaise) == if(e is RCE && e.raise == myRaise) e.value else throw e