【发布时间】:2016-10-14 02:34:05
【问题描述】:
我在 Scala 中测试了尾递归优化的性能。所以我在eclipse和sbt中都对其进行了测试。但是,我只得到尾递归版本的工作比正常版本差得多的结果。我想知道它的原因。
这是我的代码。
package MyList
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List { // companion object
def sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x, xs) => x+sum(xs)
}
def sum_tail_recursion(ints: List[Int]): Int = {
@scala.annotation.tailrec
def helper(ls: List[Int], res: Int): Int = ls match {
case Nil => res
case Cons(x, xs) => helper(xs, res+x)
}
helper(ints, 0)
}
def generate_tail_recursion(n: Int): List[Int] = {
@scala.annotation.tailrec
def helper(x: Int, ls: List[Int]): List[Int] = x match {
case 0 => ls
case x => helper(x-1, Cons(x, ls))
}
helper(n, Nil)
}
def generate(n: Int): List[Int] = n match {
case 0 => Nil
case x => Cons(x, generate(x-1))
}
def time[A](block: => A): A = {
val t0 = System.nanoTime()
val result = block
val t1 = System.nanoTime()
println("Elapsed time: " + (t1-t0) + "ns")
result
}
}
另外,我发现generate(10000) 会导致堆栈溢出,但generate_tail_recursion(10000) 不会。 (但后一种会导致一些toString错误。我该如何解决呢?)
那么,如何通过在 Scala 中使用尾递归来提高性能呢?谢谢!
更新:
这是错误。
当我运行“生成(10000)”时:
java.lang.StackOverflowError
at scala.runtime.BoxesRunTime.boxToInteger(BoxesRunTime.java:70)
at MyList.List$.generate(List.scala:56)
at MyList.List$.generate(List.scala:56)
at MyList.List$.generate(List.scala:56)
at MyList.List$.generate(List.scala:56)
当我运行generate_tail_recursion(10000):
java.lang.StackOverflowError
at scala.collection.AbstractIterator.addString(Iterator.scala:1157)
at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:286)
at scala.collection.AbstractIterator.mkString(Iterator.scala:1157)
at scala.runtime.ScalaRunTime$._toString(ScalaRunTime.scala:170)
at MyList.Cons.toString(List.scala:5)
at java.lang.String.valueOf(Unknown Source)
at scala.collection.mutable.StringBuilder.append(StringBuilder.scala:197)
at scala.collection.TraversableOnce$$anonfun$addString$1.apply(TraversableOnce.scala:327)
at scala.collection.Iterator$class.foreach(Iterator.scala:727)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
at scala.collection.TraversableOnce$class.addString(TraversableOnce.scala:320)
at scala.collection.AbstractIterator.addString(Iterator.scala:1157)
at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:286)
at scala.collection.AbstractIterator.mkString(Iterator.scala:1157)
at scala.runtime.ScalaRunTime$._toString(ScalaRunTime.scala:170)
【问题讨论】:
-
你能发布确切的错误吗?
-
@Yawar 我更新了它。谢谢!!
-
当你说'尾递归版本的工作比正常的差很多'时,你的意思是运行时速度更差,还是你得到这个错误?
-
@Yawar 我的意思是运行速度。理论上,尾递归版本应该比正常的快吧?
标签: scala stack-overflow tail-recursion