满足提供的条件时如何从传递给递归函数的lambda中断 [英] how to break from lambda passed to recursive function when provided condition met
问题描述
我正在编写自定义loop
dsl,我希望它的用法如下所示
I am writing a custom loop
dsl and I want it's usage to look like below
var counter1 = 0
var counter2 = 0
loop {
counter1 += 1
println(counter1)
stopIf(counter1 == 5) // loop should terminate here and not execute rest of the code if condition matches
counter2 += 2
println(counter2)
stopIf(counter2 == 8) // loop should terminate here and not execute rest of the code if condition matches
}
我有以下代码,该代码允许我在loop
主体中的任意位置多次编写stopIf
,但是当条件匹配时,它不会立即终止,而是执行其余的循环主体,然后终止.
I have following code which does allows me to write stopIf
any number of times and anywhere in the loop
body but when condition matches it does not terminate immediately but executes rest of the loop body and then terminates.
@UseExperimental(ExperimentalTime::class)
open class Loop {
var stop = false
val loopInterval = 1.seconds
suspend fun loop(block: suspend () -> Unit): Unit = loop(loopInterval, block)
suspend fun loop(minimumInterval: Duration, block: suspend () -> Unit): Unit =
loopWithoutDelay { delayedResult(maxOf(minimumInterval, loopInterval), block) }
private suspend fun loopWithoutDelay(block: suspend () -> Unit) {
block()
if (stop) return else loopWithoutDelay(block)
}
suspend fun <T> delayedResult(minDelay: Duration, f: suspend () -> T): T = coroutineScope {
val futureValue = async { f() }
delay(minDelay.toJavaDuration())
futureValue.await()
}
fun stopIf(condition: Boolean) {
if (condition) {
stop = condition // once stop condition matches, then do not override it with following false condtions
}
}
}
@ExperimentalTime
suspend fun loop(block: suspend Loop.() -> Unit) =
Loop().run { loop { block(this) } }
我尝试将return
与label
一起使用,但是没有用. 有什么办法可以实现这一目标?
I have tried to use return
with label
but it did not work. Is there any way I can achieve this?
推荐答案
例如,可以通过抛出轻量级异常来实现.您必须声明自定义例外:
It can be done for example with throwing a lightweight exception. You have to declare custom exception:
class LoopStopException : Throwable("Stop look", null, false, false) // lightweight throwable without the stack trace
并将其捕获在loopWithoutDelay
中:
private suspend fun loopWithoutDelay(block: suspend () -> Unit) {
try {
while (true) {
block()
}
} catch (e: LoopStopException) {
//do nothing
}
}
这篇关于满足提供的条件时如何从传递给递归函数的lambda中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!