We are working with Kotlin's Result class and the mapCatching function, which takes a transformation function that may return an arbitrary type. In our case, the transformation itself can fail, so we have it return another Result object. (We could of course also throw an Exception in the transformation function but for consistency, I guess it makes sense to also use Result there. If not, please let use know.)
However, when we do so, we end up with nested Result<Result<T>> objects, which complicates handling the result. Is there a way to avoid this nesting and flatten the result to a single Result<T>?
When asking ChatGPT, the answer is to introduce an extension function like this:
inline fun <T, R> Result<T>.flatMapCatching(transform: (T) -> Result<R>): Result<R> {
return fold(
onSuccess = { transform(it) },
onFailure = { Result.failure(it) }
)
}
Which of course makes sense 😄 But it leads me to the question: Why this is not part of Kotlin's standard implementation? Is there any cleaner way to handle the nested Result<Result<T>> objects?
Side note: I am very new to Kotlin and I only joined the team recently which itself is currently transitioning from writing code in Rust, where it seems there is a different Result implementation. So maybe we are just missing the right resources to come to a good conclusion here. So if this question has already be answered, please guide us to that resource. Until now, we e.g. have read Roman Elizarov – Kotlin and Exceptions, but it did not really help us.
mapCatching is designed to catch an exception that is thrown in the lambda. That is, the operation you are doing in the lambda should not return another Result<T> - it should just throw an exception to indicate it failed.
If you can change the signature of whatever method you are calling in mapCatching, you should. Change it to throw an exception instead of returning a Result<T>.
Otherwise, you can use getOrThrow() to throw the exception wrapped inside the Result<T>.
// suppose someOperation returns a Result<T> and you cannot change it to throw an exception instead.
someResult.mapCatching { someOperation().getOrThrow() }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With