Jonathan Beaudoin Jonathan Beaudoin - 2 months ago 17
Java Question

Kotin How to Specify Return Label When Enclosed in Lambda

Ran into an issue when making a EntityContainer for a game (a container of Lists on NPCs, Players, Objects etc). When overriding the invoke operator and in the case where my code is wrapped inside of a parent lambda, I have no way to add a

return
statement.

import java.util.*

fun main(args: Array<String>) {
val container = Container<String>()
container.addList(listOf("h", "e", "l", "l", "o"))
container.addList(listOf(" "))
container.addList(listOf("w", "o", "r", "l", "d", "!"))

Emptylambda {
container[String(), Any(), Any()].forEach {
val myCondition = true
if (myCondition) return@forEach

print(it)
}
}

println("\n\n")

Emptylambda {
container[String(), Any(), Any()] {
val myCondition = true
if (myCondition) return //Does not compile

print(it)
}
}

}


class Container<E> {

private val lists = ArrayList<List<E>>(10)

fun addList(list: List<E>) = lists.add(list)

fun forEach(action: (E) -> Unit): Unit {
lists.forEach {
it.forEach {
action(it)
}
}
}

operator fun invoke(action: (E) -> Unit) = this.forEach { action(it) }

operator fun get(vararg ignored: Any): Container<E> { return this }
}

object Emptylambda {
operator fun invoke(action: () -> Unit) {
action()
}
}


Here is the error:

Error:(43, 21) Kotlin: 'return' is not allowed here


This is a small sample of something I wrote to easily reproduce the issue. A realworld example would be as follows.

GameScreen {
entities[EntityType.PLAYER, EntityType.NPC] {
val entity = it
if (!entity.isReady()) return //Cant use return here
//Draw onto screen
}
}

Answer

If you want to return from the inner lambda you can by using return at label:

 Emptylambda outer@ {
     container[String(), Any(), Any()] inner@ {  // <--- add label here
        val myCondition = true
        if (myCondition) return@inner            // <--- exits from lambda 

        print(it)
    }
}

But you cannot return all the way to label outer.