0

I have a function that catches recoverable exceptions and returns a fallback

private fun <T> safely(block: () -> T, fallback: T): T {
    return try {
        block()
    } catch(exc: SomeException) {
        // Log the exception/do some logic
        fallback
    }
}

I want to be able to add this to the public methods of my class e.g.

fun doSomething(): List<String> = safely({
    val list = mutableListOf<String>("Hello")
    fun someCheck1() = false // Some boolean value
    fun someCheck2() = true // Some boolean value
    do {
        if(someCheck2()) {
            return arrayListOf<String>("Hello", "World")
        }
    } while (someCheck1())
    return list
}, arrayListOf<String>())

However I get compiler errors 'return' is not allowed here

Yet if I remove the return then my return in the loop no longer works and it gets highlighted in my IDE with warning the expression is never used

How can I maintain this type of return logic within a Lambda?

Playground Example

2
  • Would using a when expression help ? Commented Nov 29, 2019 at 8:59
  • Not in this case I don't think. I've probably oversimplified the code for the sake of this example Commented Nov 29, 2019 at 9:54

2 Answers 2

2

Try

fun doSomething(): List<String> = safely(
    {
        val list = mutableListOf<String>("Hello")
        fun someCheck1() = false // Some boolean value
        fun someCheck2() = true // Some boolean value
        do {
            if (someCheck2()) {
                return@safely arrayListOf<String>("Hello", "World")
            }
        } while (someCheck1())
        list
    }
, arrayListOf<String>())

For further reference, check Using return inside a lambda?

Or you can also extract your block into a separate function (i.e. someCheckFunction(): List<String>), and have fun doSomething() = safely({ someCheckFunction() }, arrayListOf()), but I guess you want to maintain lambda code like above.

Sign up to request clarification or add additional context in comments.

1 Comment

Perfect thank you! for whatever reason I had tried return@doSomething list but not return@safely list
1

return arrayListOf<String>("Hello", "World") here tries to return a value from doSomething function rather than from the lambda passed to safely. However, such return is non-local, since it tries to exit from the function that is not on the top of stack, and therefore it is prohibited.

Another option here is to make safely function inline:

inline fun <T> safely(block: () -> T, fallback: T): T { ... }

and then you'll be able to make a non-local return from block lambda function passed to it.

1 Comment

Nice i've not used inline before

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.