我最近读过关于蹦床作为消除尾部呼叫的方法。我想将我的一个功能转换为利用蹦床的东西,但我很难开始(我从OO世界来到这里)。
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)
}
}
具体来说,如果我想要在“更多”()'声明,是吗?
答案 0 :(得分:2)
您的buildTree
方法不会进行任何尾调用,因此无法利用蹦床。尾调用是当方法的返回值是另一个方法调用的结果时的优化。它允许堆栈帧替换为被调用函数的堆栈帧。如果没有尾调用优化,递归函数调用将导致堆栈大小增加,从而可能导致堆栈溢出。您的buildTree方法会自行调用两次,但原始堆栈帧必须保留,以便在创建新Node
时可以合并两个函数调用的结果。
JVM没有内置支持尾部优化,但Scala有一个函数调用自身的尾调用。 Scala通过跳转到函数的开头来替换这些递归函数调用,从而有效地将递归转换为迭代。不幸的是,这对于共同递归调用不起作用(例如,当方法A调用调用A的B时)。此处可以使用蹦床,或者基于特殊的monad,或者滥用异常处理。没有理由在其他地方使用蹦床。