Hi! What’s the difference between approach with Ra...
# arrow
n
Hi! What’s the difference between approach with Raise + error classes and checked exceptions that were considered as “bad” in kotlin and were removed from the language? I’m tend to try arrow in my new project, and this question will probably arise from my colleagues and I don’t have a good answer for it.
ł
one bad thing about checked exceptions in java is that they do not propagate through lambdas
c
The main difference is that checked exceptions were not compatible with lambdas. For example, you cannot throw a checked exception inside
Stream.map
in Java. With the growing popularity of lambda-based programming, this made checked exceptions completely unusable. Also, exceptions are dealt with very differently from "normal" values: you have to use try-catch, you have to use @Throws, etc. With Arrow, it's all just normal Kotlin code, like you could do for any other value.
There's also a bit of a different mindset in Java and Kotlin. In Java, devs want everything to be explicit. Although Kotlin devs mostly agree, there is a growing pattern of code-coloring (specific functions that can only be called inside other functions), think
inline
functions, the
reified
keyword, the
suspend
keyword, the
@Composable
annotation…
Raise
is the same pattern adapted to error management.
Also, I believe
Raise
is more performant than checked exceptions because it doesn't generate the stacktrace, which is an expensive operation (but I could be wrong on that, I'm not an expert)
2
s
Also referential integrity of otherwise pure functions is violated by those that catch (not throw) exceptions, making them non-pure (Google it as of why).
c
@streetsofboston wouldn't that be the same with
Raise
?
ł
that is intereseting question, in my understanding, the usage of raise function itself is pure, but the implementation of the raise method is non-pure (because it is throwing an exception), but this is only the implementation detail, hidden in the arrow library, am I correct?
y
Raise
is absolutely referentially transparent. The implementation obviously uses non-pure things, but so does
map
for instance lol. Taking in a
Raise
instance is you declaring that you need some error-handler in scope that can handle that error.
Raise
doesn't allow you to catch something that was intended for a different
Raise
instance, and for good reason.
☝️ 1
K 1
mind blown 1
👍 1
n
Thank you very much for the responses 🙏
r
I know Kotlin doesn’t support checked exceptions. However, they had their rationale in Java at the beginning of the language journey. The aim of checked exceptions was to make it clear in a function signature how it could fail. Within this aspect, they are very close to using an
Either
or a
Result
. Unchecked exceptions were made for bugs and unexpected errors. The exception framework needed to be understood by developers from the very beginning. So. the language evolved, preferring unchecked exceptions, which compose well with lambdas but lack compiler support.
c
So. the language evolved, preferring unchecked exceptions, which compose well with lambdas but lack compiler support.
This is mostly because they are part of the signature, not the type. This is why they couldn't be supported by lambdas, etc. In Kotlin, context receivers are part of the type, so there's no need for new concepts everywhere to make them work.
r
Yep, I was talking about a bit of language history
👍 1