Why is it possible to assign recursive lambdas to non-lazy vals in Scala?

陌路散爱 提交于 2019-12-02 04:15:18

问题


In the following statement the val f is defined as a lambda that references itself (it is recursive):

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

I've tried it in the REPL, and it compiles and executes correctly.

According to the specification, this seems like an instance of illegal forward referencing:

In a statement sequence s[1]...s[n] making up a block, if a simple name in s[i] refers to an entity defined by s[j] where j >= i, then for all s[k] between and including s[i] and s[j],

  • s[k] cannot be a variable definition.
  • If s[k] is a value definition, it must be lazy.

The assignment is a single statement, so it satisfied the j >= i criteria, and it is included in the interval of statements the two rules apply to (between and including s[i] and s[j]).

However, it seems that it violates the second rule, because f is not lazy.

How is that a legal statement (tried it in Scala 2.9.2)?


回答1:


You probably tried to use this in the REPL, which wraps all contents in an object definition. This is important because in Scala (or better: on the JVM) all instance values are initialized with a default value, which is null for all AnyRefs and 0, 0.0 or false for AnyVals. For method values this default initialization does not happen, therefore you get an error message in this case:

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 }
                                                           ^

This behavior can even lead to weird situations, therefore one should be careful with recursive instance values:

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

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


来源:https://stackoverflow.com/questions/24812376/why-is-it-possible-to-assign-recursive-lambdas-to-non-lazy-vals-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!