这是尾递归还是Kotlin编译器有问题?

时间:2019-02-17 11:13:12

标签: intellij-idea kotlin tail-recursion

如果以下函数是尾部递归的或者Kotlin编译器或IntelliJ Idea有问题,我会感到困惑。

根据我的理解,这不适合进行with recursive cte(greatest_id, ids, total) as ( select id, CAST(id AS CHAR(5)) AS ids, val from tbl union all select tbl.id, concat(cte.ids, tbl.id), cte.total + tbl.val from cte inner join tbl on tbl.id > cte.greatest_id and cte.total + tbl.val <= 6 ) select ids, total from cte 优化,因为递归调用不是最后一个调用。这是代码;

tailrec

根据Kotlin文档,论坛帖子和我发现的一些答案,应该将此使用标记为警告。

我也对IntelliJ Kotlin编译器启用了编译器警告。但是我在IntelliJ(IntelliJ IDEA 2018.3.3(Ultimate Edition-Build#IU-183.5153.38,建于2019年1月9日))或Gradle(5.2)上都没有看到任何警告。我在Java 1.8_141上使用Kotlin 1.3

我在这里想念什么? (我想确保我正确使用 tailrec fun hasRouteBetween(first: GraphNode, second: GraphNode): Boolean { if (first.id == second.id) return true if (second.children.isEmpty()) return false second.visited = true for (child in second.children) { if (!child.visited) { return hasRouteBetween(first, child) } } return false } data class GraphNode(val id: Int, var visited: Boolean = false, val children: LinkedList<GraphNode>) ,因为此代码将与其他人共享)。任何帮助,将不胜感激。

1 个答案:

答案 0 :(得分:2)

此函数 是尾部递归的。要使尾部递归起作用,您需要的是递归调用直接产生该函数的结果,而不需要在进行调用的位置进行任何其他处理。这样可以确保在递归调用开始之前可以清除当前函数调用的堆栈,因为不再需要那里的数据。

因此,例如,此实现将无法正常工作,因为它需要在递归的每个级别上保持堆栈的状态:

var result = false
for (child in second.children) {
    if (!child.visited) {
        if (hasRouteBetween(first, child)) {
            result = true
        }
    }
}
return result

您的函数无需执行此类操作。在您的if语句中,您进行递归调用,然后将当前调用正在进行的所有操作都排除掉,因为递归调用的结果就是您所需要的。


我不确定您的算法本身是否正确,因为第一个未访问的孩子将是唯一一个递归调用的孩子。