在以下语句中,将val f定义为引用自身的lambda(它是递归的):

val f: Int => Int = (a: Int) =>
    if (a > 10) 3 else f(a + 1) + 1 // just some simple function


我已经在REPL中尝试过,它可以正确编译并执行。

根据规范,这似乎是非法前向引用的一个实例:


在语句序列中,s[1]...s[n]组成一个块,如果简单的话
s[i]中的名称是指由s[j]定义的实体,其中j >= i
那么对于s[k]s[i]之间的所有s[j]


s[k]不能是变量定义。
如果s[k]是值定义,则必须为lazy



该赋值是一条语句,因此它满足j >= i条件,并且包含在两个规则所适用的语句间隔中(介于s[i]s[j]之间)。

但是,它似乎违反了第二条规则,因为f不是惰性的。

法律声明如何(在Scala 2.9.2中尝试过)?

最佳答案

您可能试图在REPL中使用此功能,该功能将所有内容包装在对象定义中。这很重要,因为在Scala(或更好的是:在JVM上)中,所有实例值都使用默认值初始化,对于所有nullAnyRefs,该值均为0;对于0.0,其值为falseAnyVals 。对于方法值,不会发生默认初始化,因此在这种情况下,您会收到一条错误消息:

scala> object x { val f: Int => Int = a => if (a > 10) 3 else f(a+1)+1 }
defined object x

scala> def x { val f: Int => Int = a => if (a > 10) 3 else f(a+1)+1 }
<console>:7: error: forward reference extends over definition of value f
       def x { val f: Int => Int = a => if (a > 10) 3 else f(a+1)+1 }
                                                           ^


这种行为甚至可能导致奇怪的情况,因此在使用递归实例值时应格外小心:

scala> val m: Int = m+1
m: Int = 1

scala> val s: String = s+" x"
s: String = null x

07-24 18:12