满足提供的条件时如何从传递给递归函数的lambda中断 [英] how to break from lambda passed to recursive function when provided condition met

查看:94
本文介绍了满足提供的条件时如何从传递给递归函数的lambda中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写自定义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) } }

我尝试将returnlabel一起使用,但是没有用. 有什么办法可以实现这一目标?

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆