Scala括号java.lang.StackOverflower错误

Scala括号java.lang.StackOverflower错误,scala,stack-overflow,Scala,Stack Overflow,我在处理这个愚蠢的递归代码时遇到了麻烦。它在不应该的地方抛出StackOverflowerError错误,或者我认为是这样。我查看了字节码,发现了问题 有人能给我解释一下Scala在引擎盖下干什么吗 JVM和Scala版本: $ java -version java version "1.6.0_45" Java(TM) SE Runtime Environment (build 1.6.0_45-b06-451-11M4406) Java HotSpot(TM) 64-Bit Server V

我在处理这个愚蠢的递归代码时遇到了麻烦。它在不应该的地方抛出StackOverflowerError错误,或者我认为是这样。我查看了字节码,发现了问题

有人能给我解释一下Scala在引擎盖下干什么吗

JVM和Scala版本:

$ java -version
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06-451-11M4406)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01-451, mixed mode)

$ scala -version
Scala code runner version 2.10.3 -- Copyright 2002-2013, LAMP/EPFL
以下是小程序:

package objsets

class Recur(layer: Int, value: Int) {
  def inner = new Recur(layer - 1, value + 1)
  def getVal: Int = {
    if (layer <= 0) value
    else  // if surrond these 2 expressions with brackets, error will go away
      //{  
        print("");   
        inner.getVal
      //}
  }
}

object Recur {
  def main(args: Array[String]) = {
    println((new Recur(0, 5)).getVal) // throw java.lang.StackOverflowError
  }
}
括号内:

public int getVal();
  Code:
   0:   aload_0
   1:   getfield    #25; //Field layer:I
   4:   iconst_0
   5:   if_icmpgt   18
   8:   aload_0
   9:   getfield    #27; //Field value:I
   12:  invokestatic    #41; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
   15:  goto    29    // not sure why it goes to 29
   18:  getstatic   #46; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   21:  ldc #48; //String
   23:  invokevirtual   #52; //Method scala/Predef$.print:(Ljava/lang/Object;)V
   26:  getstatic   #58; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
   29:  pop
   30:  aload_0
   31:  invokevirtual   #60; //Method inner:()Lobjsets/Recur;
   34:  invokevirtual   #62; //Method getVal:()I
   37:  ireturn
public int getVal();
  Code:
   0:   aload_0
   1:   getfield    #25; //Field layer:I
   4:   iconst_0
   5:   if_icmpgt   15
   8:   aload_0
   9:   getfield    #27; //Field value:I
   12:  goto    30
   15:  getstatic   #40; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   18:  ldc #42; //String
   20:  invokevirtual   #46; //Method scala/Predef$.print:(Ljava/lang/Object;)V
   23:  aload_0
   24:  invokevirtual   #48; //Method inner:()Lobjsets/Recur;
   27:  invokevirtual   #50; //Method getVal:()I
   30:  ireturn
问题似乎在于无括号版本中的“goto 29”


有人能给我解释一下Scala在引擎盖下干什么吗?这是因为Scala试图找出(print(“”;internal.getVal)的值类型,但在编译时无法做到这一点吗?

如果else块包含多个语句,则需要用括号括住这些语句,否则,print语句是else块中唯一的语句,并且您的
getVal
方法将始终返回
internal.getVal

不带括号,您的代码相当于:

class Recur(layer: Int, value: Int) {
  def inner = new Recur(layer - 1, value + 1)
  def getVal: Int = {
    if (layer <= 0) value else print("")  
    return inner.getVal // added explicit return
  }
}
当<代码>图层
class Recur(layer: Int, value: Int) {
  def inner = new Recur(layer - 1, value + 1)
  def getVal: Int = {
    return (if (layer <= 0) value
            else {  
              print("");   
              inner.getVal
            }
    )
  }
}