java - Scala StackOverflowError 而 Java 可以处理它

标签 java scala

我倾向于在 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/

相关文章:

java - 用于开发和生产的不同 PersistenceConfig.java

java - Java 中是否有可能让一个 map 得到另外两个 map 的支持?

scala - 在Scala中, `println(1,2)`如何运作?

Java 集合属性初始化 - 最佳实践

java - 如何编辑现有的 eclipse 插件?

Java "Content not allowed in prolog.”

Scala 2.8 突破

scala - 在 Scala 中附加到 Seq 无法编译

scala - 从 Spark 服务器执行 SFTP 时,大型机服务器上的记录级别数据截断

java - Scala @specialized 注解无限递归?