kotlin runCatching force default return

Viewed 49

The constructor of runCatching in kotlin annoys me.
If it is supposed to replace try{}catch{} why I need to still have a default return when using it?

IS THERE ANY WAY TO AVOID DEFAULT RETURN?

example

fun foo(): String {

    objects
        .runCathing { anyFunctionThatReturnsString() }
        .onFailure {
            return "error"
        }
        .onSucess {
            return "sucess"
        }

    return ""
}

on standard java try{}catch{} if i have return inside try and inside catch i don't need a default return out of the block....

why on kotlin i need it? any way to avoid this?

3 Answers

Because runCatching doesn't return the type directly but returns Kotlin Result

    fun foo(): String {
        val foo: Result<String> = runCatching {
            ""
        }.onFailure { 
            ""
        }.onSuccess { "" }
        
        return foo.getOrElse { "" }
    }

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/run-catching.html

Since every lambda is returning Result you can collapse to the return like this:

fun foo(): String {
        return runCatching {
            ""
        }.onFailure {
            ""
        }.onSuccess { 
            "" 
        }.getOrNull() ?: ""
    }

If you want to use runCatching, you are probably doing something wrong with your code, unless you are already out of your domain layer and for example generating error message for UI.

If you really want to do something like this, I suggest you just create your own method/extension. For example (I find a bit weird to have 2 blocks for "success" - running code and then handling success):

fun foo(): String {
    return chooseBetterName(
        { "" },
        onSuccess = { "success" },
        onFailure = { "error" }
    )
}

fun <T> chooseBetterName(block: () -> T, onSuccess: (T) -> T, onFailure: (Exception) -> T): T {
    return try {
        onSuccess(block())
    } catch (e: Exception) {
        onFailure(e)
    }
}

If it is supposed to replace try{}catch{}...

It's not supposed to replace try/catch.

It's clumsy to use like that because that's not what runCatching is for. You should use try/catch:

fun foo(): String {
    return try {
        objects.anyFunctionThatReturnsString()
        "success"
    } catch (e: Exception) { // In practice this should be specific to the expected errors that the above function can throw.
        "error"
    }
}
Related