Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 为什么这个函数不适合尾部递归?_Kotlin_Tail Recursion - Fatal编程技术网

Kotlin 为什么这个函数不适合尾部递归?

Kotlin 为什么这个函数不适合尾部递归?,kotlin,tail-recursion,Kotlin,Tail Recursion,以下示例中的函数send()递归调用自身: internal inner class RouteSender( val features: List<Feature>, val exchange: GrpcUniExchange<Point, RouteSummary> ) { var result: AsyncResult<RouteSummary>? = null // Set in stub for recordR

以下示例中的函数
send()
递归调用自身:

internal inner class RouteSender(
        val features: List<Feature>,
        val exchange: GrpcUniExchange<Point, RouteSummary>
) {
    var result: AsyncResult<RouteSummary>? = null // Set in stub for recordRoute.

    fun send(numPoints: Int) {
        result?.let {
            // RPC completed or err'd before sending completed.
            // Sending further requests won't error, but they will be thrown away.
            return
        }

        val index = random.nextInt(features.size)
        val point = features[index].location
        println("Visiting point ${RouteGuideUtil.getLatitude(point)}, " +
                "${RouteGuideUtil.getLongitude(point)}")
        exchange.write(point)
        if (numPoints > 0) {
            vertx.setTimer(random.nextInt(1000) + 500L) { _ ->
                send(numPoints - 1)
            }
        } else {
            exchange.end()
        }
    }
}
内部内部类RouteSender(
val功能:列表,
val交换:GrpcUniExchange
) {
变量结果:AsyncResult?=null//在recordRoute的存根中设置。
趣味发送(numPoints:Int){
结果呢?让我来{
//RPC已完成或发送前出错已完成。
//发送进一步的请求不会出错,但会被丢弃。
回来
}
val index=random.nextInt(features.size)
val point=要素[索引]。位置
println(“访问点${RouteGuideUtil.getLatitude(点)},”+
“${RouteGuideUtil.getLongitude(点)}”)
exchange.write(点)
如果(numPoints>0){
vertx.setTimer(random.nextInt(1000)+500L){{uU->
发送(numPoints-1)
}
}否则{
exchange.end()
}
}
}
可以重新写入它,以便执行的最后一个操作是对自身的递归调用:

...
if (numPoints <= 0) {
                exchange.end()
            } else {
                vertx.setTimer(random.nextInt(1000) + 500L) { _ ->
                    send(numPoints - 1)
                }
            }
...
。。。
if(numPoints)
发送(numPoints-1)
}
}
...
但是,如果我将其标记为
tailrec
函数,我会收到一条警告,提示递归调用不是尾部调用。这不会停止编译程序的成功运行。但是,为什么这不是尾部调用呢

报告说:

要符合
tailrec
修饰符的条件,函数必须调用自身 作为它执行的最后一个操作。当 递归调用之后有更多的代码,您不能使用它 在try/catch/finally块中

这不在try/catch/finally块内,递归调用后没有更多的代码。这意味着此代码块不符合尾部递归优化的条件是什么

我将尝试回答我自己的问题,因为它没有返回值。根据讨论,这就是我所能想到的。想法?

尽管您的方法似乎包含对自身的调用,但实际上它根本不是递归方法

send
的调用出现在闭包内部。这意味着它不会立即被调用。只有在调用闭包本身时才会被调用。在您的情况下,这是由计时器完成的。它将发生在当前调用堆栈之外,甚至可能发生在当前线程之外

在任何情况下,最后一个调用都是对
vertx.setTimer

的调用。尽管您的方法似乎包含对自身的调用,但实际上它根本不是递归方法

send
的调用出现在闭包内部。这意味着它不会立即被调用。只有在调用闭包本身时才会被调用。在您的情况下,这是由计时器完成的。它将发生在当前调用堆栈之外,甚至可能发生在当前线程之外


在任何情况下,最后一个调用都是对
vertx的调用。setTimer
Kotlin允许内联闭包函数,它将内联闭包函数用于它自己的许多库函数,例如forEach。如果从内联闭包调用tailrec,那么在从内联闭包返回的所有函数都从外部函数返回之后,tailrec可能会工作


但是,如上所述,这是一个计时器回调函数,因此根据定义,它不能是内联调用,也不能是尾部递归。

Kotlin允许内联闭包函数,它将内联闭包函数用于它自己的许多库函数,例如forEach。如果从内联闭包调用tailrec,它可能会工作,毕竟它是从内联闭包返回的e闭包从外部函数返回

但是,如上所述,这是一个计时器回调函数,因此根据定义,它不能是内联调用,也不能是尾部递归调用