Scala:Tail Recursion和ListBuffer

时间:2014-01-14 20:31:49

标签: scala tail-recursion

我正在学习Scala,在这样做的过程中,我遵循Brien的15个练习(http://www.knowing.net/index.php/2006/06/16/15-exercises-to-know-a-programming-language-part-1/)。在第二个练习中,我应该实施Haar转换。我实施了大部分内容 但是用尾递归的返回值挣了好几个小时。由于编译器不编译++ - 或更精确地编译行haar(averages) ++ haar(averagesD)

  • 我在递归函数中做错了什么?
  • 你能否就我的代码给我其他反馈?

代码:

import scala.collection.mutable.ListBuffer
import scala.annotation.tailrec

object haarWavelet2 {

  def avg(tpl:Tuple2[Double, Double]):Double = (tpl._1 + tpl._2) / 2.
  def avgD(tpl:Tuple2[Double, Double]):Double = (tpl._1 - tpl._2) / 2
  def total_avg(nums:ListBuffer[Double]):Double = nums.sum / nums.length

  @tailrec 
  def haar(nums:ListBuffer[Double]):ListBuffer[Double] = {

    if (nums.length == 1) {return nums}

    val buffer = new ListBuffer[Tuple2[Double, Double]]
    for (i <- 0 to nums.length-1 by 2) buffer.append((nums(i), nums(i+1)))

    val averages = for(tpl <- buffer) yield avg(tpl)
    val averagesD = for(tpl <- buffer) yield avgD(tpl)

    haar(averages) ++ haar(averagesD) // does not compile
    }

  def main(args: Array[String]): Unit = {
          print(haar(ListBuffer(8., 5., 6., 2.)))
  }
}

2 个答案:

答案 0 :(得分:5)

尾递归有以下形式:

def func(x..., value){
  if(condition) return value
  else func(y..., value')
}

如果您查看此表单,您看到的是为了评估func我需要的只是func本身,但使用不同的参数集。因此,只有一个项目可以放在堆栈上,它可以很容易地转换为迭代算法。

您实施的内容如下:

def func(x...){
  if(condition) return value
  else func(y...) + func(z...)

请注意,为了评估func您必须首先评估func,运算符+,然后再评估'func'。因此,需要将3个项目放在堆栈上,并且具有非常实际的评估顺序,这不适合尾部调用优化。

答案 1 :(得分:2)

在上面的@wheaties结构之后,尾递归函数看起来像这样,

@tailrec 
def haar(nums:ListBuffer[Double]): ListBuffer[Double] = {

    def haarAcc (nums:ListBuffer[Double], acc:ListBuffer[Double]): ListBuffer[Double] = {
      if (nums.length == 1) return acc

      // val nums_updated ...

      haarAcc(nums_updated, averages ++ averagesD) 
    }

    haarAcc(nums, ListBuffer())
}