When using `Either.catch()` I find myself wanting ...
# arrow
e
When using
Either.catch()
I find myself wanting to treat it like
either {}
and use various DSL methods provided by
Raise
inside the catch() function. Since it doesn't provide that context, is this the correct way?
Copy code
either {
    Either.catch() { ... }.bind()
}
y
This is correct yes!
result
builder does something similar btw, so this might be a good definition for a util:
Copy code
result(block).fold(::Right, ::Left)
s
Yes, that’s the correct way. Only couple days ago we had a similar question, https://kotlinlang.slack.com/archives/C5UPMM0A0/p1749141591846199 I guess it’s time to add a section to the docs, or would this warrant an additional builder? 🤔
y
I think an
Either.catching
or similarly-named builder might be warranted here, implemented in a similar way to
result {}
(i.e. using
fold
)
s
We should collect some use-cases because it seems everyone is doing something slightly different so providing a common DSL might be tricky. @Erik Dreyer do you work with EitherThrowable, A, and you’re using which DSL functions? Mostly bind? I assume this is when interacting with some libraries or platform APIs? You potentially just skip the DSL and just use exceptions directly inside Either.catch. If you’re using i.e.
ensure(false) { RuntimeException() }
then you’re still paying the penalty of exceptions anyway. So you might as well just
throw
. If that’s not the case then the last 2 snippets from the linked thread might work nicely for you.
👀 1
e
This came up because I was reviewing some code and saw this gem in a PR:
Copy code
private fun getToken(tokenId: UUID): Either<DataStorageError, Decrypted> = either {
    Either.catch {
        tokenDao.getToken(tokenId) ?: throw NoSuchElementException("Token not found for tokenId: $tokenId")
    }.mapLeft { exception -> handleTokenExceptions(exception)
    }.bind()
}
I get what it does, but I can't help feeling there's a less awkward way to express this. maybe instead of this
Copy code
tokenDao.getToken(tokenId) ?: throw NoSuchElementException("Token not found for tokenId: $tokenId")
you could do
Copy code
ensureNotNull(tokenDao.getToken(tokenId)) { NoSuchElementException(...)}
and deal with it at the outer
either {}
block
I'm told
tokenDao.getToken(tokenId)
can throw other exceptions, so we still need the
Either.catch
s
There is quite some redundant things going on 😅 So it
throw NoSuchElementException("Token not found for tokenId: $tokenId")
if
getToken
is
null
, but can
getToken
also throw? If not, then it's probably just,
tokenDao.getToken(tokenId).right() ?: handleTokenExceptions(?)
.
😂 1
e
for sure
s
Any
either { }
with a single
bind
and nothing after it is probably redundant as well. This could also just be:
Copy code
Either.catch {
    tokenDao.getToken(tokenId) ?: throw NoSuchElementException("Token not found for tokenId: $tokenId")
}.mapLeft { exception -> handleTokenExceptions(exception) }
👍 1
e
gracias
kodee loving 1