Hello dear people! I am using the Result class a l...
# kontributors
j
Hello dear people! I am using the Result class a lot in my daily life. The only thing that, in my humble opinion, is missing in it, is a way to flatMap results! Lets say I have to perform 2 jobs that depend on each other, both returning a result, it would be great to do use it in cases like this:
Copy code
fun fetchDataForLoggedInUser(): Result<String> = fetchLoggedInUserUseCase.run()
    .flatMap { user -> fetchDataForUserUseCase.run(user) }
I of course made my own extension function (in the comment), but would you people agree that it would be a nice thing to add to the standard library as well?
Possible implementation could be:
Copy code
inline fun <T, R> Result<T>.flatMap(
    transform: (T) -> Result<R>,
): Result<R> {
    contract {
       callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
    }
    return transform(getOrElse { return failure(it) })
}
c
Well, we were just talking about this in the other thread, but this implementation is incorrect: if the
Result
contains a CancellationException, this function will execute
transform
, whereas it shouldn't since the coroutine has been cancelled. Instead, it should call
coroutineContext.ensureActive
before executing
transform
, but that requires making the entire function
suspend
.
j
I disagree, as flatMap does not catch anything, it is not its responsibility to check if a previous catching function was correctly implemented or not
c
Well, there is no standard catching function that handles CE, and you didn't give one either, so you have to assume your readers will be using
runCatching
j
But then probably all the functions in the standard library are wrong as none of them check for it
c
Yes and no. They are not meant to be used for error handling. They are correct for their intended usage (rethrowing the exception in another thread/context). They are not correct to use for generic error handling.
j
But I guess in that case a revisit of runCatching would be good as well, or a suspended version of it 🙂
c
IMO
runCatching
should just be moved back to be an internal of kotlinx.coroutines, where it belongs 😅
By nature, it can't be appropriate for error-handling: it catches
Throwable
, which is always an anti-pattern. Not a single application, and even more in the domain layer, has an appropriate way to recover from a
StackOverflowError
. And that's without counting on
OutOfMemoryError: metaspace
, there is nothing you can do to recover that.