Can't have a return inside a Runnable SAM in Kotlin?

2.2k views Asked by At

I am having the following error with this piece of code, which makes no sense to me:

fun spawnWorker(): Runnable {
    return Runnable {
        LOG.info("I am a potato!")
        return
    }
}

My IDE says this to me:

enter image description here

But the Runnable interface says otherwise:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

What is the reason why I can't have a return there, but without any return it compiles fine:

fun spawnWorker(): Runnable {
    return Runnable {
        LOG.info("I am a potato!")
    }
}
2

There are 2 answers

2
Ingo Kegel On BEST ANSWER

A plain return returns from the nearest enclosing function or anonymous function. In your example, the return is non-local and returns from spawnWorker and not from the Runnable SAM adapter. For a local return, use the labeled version:

fun spawnWorker(): Runnable {
    return Runnable {
        LOG.info("I am a potato!")
        return@Runnable
    }
}
0
voddan On

You are using a lambda-to-SAM conversion, thus trying to return from a lambda statement, which is not allowed to have a return on its own.

Your code

fun spawnWorker(): Runnable {
    return Runnable { LOG.info("I am a potato!") }
}

Means the same as

fun spawnWorker(): Runnable {
    return { LOG.info("I am a potato!") }
}

Compare it to returning an object, which is the direct translation from Java:

fun spawnWorker(): Runnable {
    return object : Runnable {
        override fun run() {
            LOG.info("I am a potato!")
            return // don't really need that one
        }
    }
}