Scala 了解如何将递归转换为蹦床
我最近读到关于蹦床是一种消除尾巴叫声的方法。我想将我的一个函数转换为使用蹦床的函数,但我现在很难开始(我来自OO世界)Scala 了解如何将递归转换为蹦床,scala,recursion,tail-recursion,trampolines,Scala,Recursion,Tail Recursion,Trampolines,我最近读到关于蹦床是一种消除尾巴叫声的方法。我想将我的一个函数转换为使用蹦床的函数,但我现在很难开始(我来自OO世界) 具体来说,如果我想在“More()”语句中进行两个不同的递归调用,可以吗 您的buildTree方法不进行任何尾部调用,因此无法利用蹦床。当一个方法的返回值是另一个方法调用的结果时,尾部调用是一种优化。它允许堆栈帧替换为被调用函数的堆栈帧。如果没有尾部调用优化,递归函数调用将导致堆栈大小增加,可能导致堆栈溢出。buildTree方法确实调用了自身两次,但必须保留原始堆栈框架,以
具体来说,如果我想在“More()”语句中进行两个不同的递归调用,可以吗 您的
buildTree
方法不进行任何尾部调用,因此无法利用蹦床。当一个方法的返回值是另一个方法调用的结果时,尾部调用是一种优化。它允许堆栈帧替换为被调用函数的堆栈帧。如果没有尾部调用优化,递归函数调用将导致堆栈大小增加,可能导致堆栈溢出。buildTree方法确实调用了自身两次,但必须保留原始堆栈框架,以便在创建新的节点时可以组合两个函数调用的结果
JVM没有内置的对tail-all优化的支持,但是Scala有一个对函数自身调用的tail调用的攻击。Scala将这些递归函数调用替换为跳转到函数的开头,有效地将递归转化为迭代。不幸的是,这不适用于共递归调用(例如,当方法A调用B而B调用A时)。这里可以使用蹦床,或者基于特殊的monad,或者滥用异常处理。没有理由在其他地方使用蹦床
def buildTree (X:DenseMatrix[Double], Y:DenseVector[Double], minBucket:Int):Node = {
// Get the split variable, split point and data for this data
val (splitVar, splitPoint, leftX, leftY, rightX, rightY) = chooseSplit(X, Y, minBucket);
// If we couldn't find a split, then we have a leaf
if(splitVar == Double.NegativeInfinity){
new Node(Y)
}else{
// Otherwise recursively build the children and create yourself as a vertex
val left = buildTree(leftX, leftY, minBucket))
val right = buildTree(rightX, rightY, minBucket))
new Node(Y, splitVar, splitPoint, left, right)
}
}