2014-04-01 74 views
0

錯誤我有一個簡單的方法來建立一個樹:尾調用優化的投擲簡單的功能

@tailrec final def buildTree (X:DenseMatrix[Double], Y:DenseVector[Double], minBucket:Int):Node = { 
     // Get the split variable, split point and 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) 
     } 

然而,當我去編譯,我得到: could not optimize @tailrec annotated method buildTree: it contains a recursive call not in tail position

我做的事情像OCaml一樣沒有任何問題。有沒有解決這個問題的方法?

+0

請參閱[這個問題]的答案(http://stackoverflow.com/questions/4785502/why-wont-the-scala-compiler-apply-tail-call-optimization-unless-a-method-is-鰭)。 – dfan

回答

1

我認爲錯誤信息是很清楚的:你的方法既不是private也不final,因此它可以被覆蓋,因此不能保證到buildTree的呼叫將轉到相同的方法。該方法需要是privatefinal

但即使它privatefinal,遞歸調用不在尾部位置。

基本上,你的尾遞歸調用既不是尾調用,也不保證是遞歸的。

+0

好的一點,我沒有注意到它甚至不是理論上的尾遞歸。 – dfan

+0

我已更新該問題。這在OCaml中沒有任何問題*。我的問題是如何讓scala執行優化(這並不複雜)。 – dave

+0

那麼,做一些尾遞歸的策略是衆所周知的:添加一個累加器,轉換爲延續傳球風格,使用蹦牀,...... –