Kotlin递归堆栈溢出

时间:2018-06-23 20:41:10

标签: recursion kotlin stack-overflow tail-recursion

我已经在Kotlin中编写了此递归函数:

fun recursive(target: String, population: Population, debugFun: (String) -> Unit) : Population {
    if (population.solution(target).toString() == target) {
        return population
    }
    debugFun.invoke(population.solution(target).toString())
    return recursive(target, population.evolve(target), debugFun)
}

它将运行不确定的时间(因为我正在使用随机性来收敛进化算法中的解)。我经常遇到堆栈溢出。 Kotlin / JVM语言的最大堆栈深度是多少?我应该以非递归方式编写函数吗?

1 个答案:

答案 0 :(得分:7)

tailrec 关键字告诉Kotlin编译器使用尾部递归。因此,它将展开递归循环到循环中,这样您就可以摆脱 StackOverflowError

tailrec fun recursive(target: String, population: Population, debugFun: (String) -> Unit) : Population {
    if (population.solution(target).toString() == target) {
        return population
    }
    debugFun.invoke(population.solution(target).toString())
    return recursive(target, population.evolve(target), debugFun)
}

因此,当使用 tailrec 时,编译器会创建与以下功能匹配的内容:

fun recursive(target: String, population: Population, debugFun: (String) -> Unit) : Population{
    var tmp = population

    while (true) {
        if (tmp.solution(target).toString() == target) {
            return tmp
        }
        debugFun.invoke(population.solution(target).toString())
        tmp = tmp.evolve(target)
    }
}

在此函数中,不再进行任何方法调用,因此没有任何内容被压入堆栈,并且我们从 StackOverflowError 中保存。

请注意,我们仍然可能陷入无休止的循环!