如果以下函数是尾部递归的或者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>)
,因为此代码将与其他人共享)。任何帮助,将不胜感激。
答案 0 :(得分:2)
此函数 是尾部递归的。要使尾部递归起作用,您需要的是递归调用直接产生该函数的结果,而不需要在进行调用的位置进行任何其他处理。这样可以确保在递归调用开始之前可以清除当前函数调用的堆栈,因为不再需要那里的数据。
因此,例如,此实现将无法正常工作,因为它需要在递归的每个级别上保持堆栈的状态:
var result = false
for (child in second.children) {
if (!child.visited) {
if (hasRouteBetween(first, child)) {
result = true
}
}
}
return result
您的函数无需执行此类操作。在您的if
语句中,您进行递归调用,然后将当前调用正在进行的所有操作都排除掉,因为递归调用的结果就是您所需要的。
我不确定您的算法本身是否正确,因为第一个未访问的孩子将是唯一一个递归调用的孩子。