我倾向于在 Scala 中编程并遇到了这个问题,Scala 代码抛出 StackOverflowErorr,而 Java 中的类似实现在抛出相同错误之前可以走得更远一些
def recursiveSum(args: Int*): Int = {
if (args.length == 0) 0
else
args.head + recursiveSum(args.tail: _*)
}
recursiveSum(5000 to 15000: _*)
我得到的错误是
java.lang.StackOverflowError
//| at scala.collection.Parallelizable$class.$init$(Parallelizable.scala:20)
//| at scala.collection.AbstractTraversable.<init>(Traversable.scala:105)
//| at scala.collection.AbstractIterable.<init>(Iterable.scala:54)
//| at scala.collection.AbstractSeq.<init>(Seq.scala:40)
//| at scala.collection.immutable.Range.<init>(Range.scala:44)
//| at scala.collection.immutable.Range$Inclusive.<init>(Range.scala:330)
//| at scala.collection.immutable.Range$Inclusive.copy(Range.scala:333)
//| at scala.collection.immutable.Range.drop(Range.scala:170)
//| at scala.collection.immutable.Range.tail(Range.scala:196)
//| at scala.collection.immutable.Range.tail(Range.scala:44)
//| at Loops$$anonfun$main$1.recursiveSum$1(Loops.scala:11)
//| at Loops$$anonfun$main$1.recursiveSum$1(Loops.scala:11)
//| at Loops$$anonfun$main$1.recursiveSum$1(Loops.scala:11)
//| at Loops$$anonfun$main$1.recursiveSum$1(Loops.scala:11)
//| at Loops$$anonfun$m
//| Output exceeds cutoff limit.
java代码是
static int recursiveSum(int... arg) {
if (arg.length == 0)
return 0;
else
return arg[0] + recursiveSum(Arrays.copyOfRange(arg, 1, arg.length));
}
public static void main(String[] args) {
System.out.println(recursiveSum(range(5000, 15000)));
}
private static int[] range(int i, int j) {
int list[] = new int[j - i + 1];
int idx = 0;
for (int s = i; s <= j; s++)
list[idx++] = s;
return list;
}
为什么 Scala 的尾递归优化没有帮助?为什么 Java 可以处理(Java 不能处理超过 15000,比如 16000)?
它们在相同的 eclipse ide 上运行,桌面计算机上默认堆栈大小为 java 7。
最佳答案
这不是尾递归。为了使函数成为尾递归函数,函数中的最后一条语句(尾部)需要是递归调用。在您的情况下,它可能看起来像,但如果您使用 @tailrec
注释来注释您的函数,您会发现它不是。其实你最后一句是加法,不是递归调用。
如果您重写您的函数以使用累加器,您将能够执行尾递归版本...
def recursiveSum(args: Int*): Int = {
@tailrec
def sumAccumulator(sum: Int, args: Int*): Int = {
if(args.length == 0) sum
else sumAccumulator(sum + args.head, args.tail: _*)
}
sumAccumulator(0, args: _*)
}
recursiveSum(5000 to 15000: _*)
关于java - Scala StackOverflowError 而 Java 可以处理它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23832463/