在以下语句中,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中尝试过)?
答案 0 :(得分:7)
您可能尝试在REPL中使用它,它将所有内容包装在对象定义中。这很重要,因为在Scala中(或者更好:在JVM上),所有实例值都使用默认值进行初始化,null
和AnyRefs
0
为0.0
或false
AnyVals
。对于方法值,此默认初始化不会发生,因此在这种情况下会收到错误消息:
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