【问题标题】:Why is it possible to assign recursive lambdas to non-lazy vals in Scala?为什么可以将递归 lambda 分配给 Scala 中的非惰性 val?
【发布时间】:2014-07-17 19:54:36
【问题描述】:

在以下语句中,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[i]s[j]之间的所有s[k]

  • s[k] 不能是变量定义。
  • 如果s[k]是一个值定义,它必须是lazy

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

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

这是一个法律声明(在 Scala 2.9.2 中尝试过)?

【问题讨论】:

    标签: scala recursion lambda definition specifications


    【解决方案1】:

    您可能尝试在 REPL 中使用它,它将所有内容包装在一个对象定义中。这很重要,因为在 Scala(或更好:在 JVM 上)中,所有实例值都使用默认值进行初始化,对于所有 AnyRefs0null0.0false 对于 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
    

    【讨论】:

    • 是的,你是对的,这是在 REPL 中。我有一种预感,它可能是这样的,我知道 Scala REPL 背后必须有一些黑魔法(Scala 毕竟是一种编译语言,所以当我看到它甚至有一个 REPL 时我有点困惑 -我只是假设它收集了您之前输入的所有语句并将它们放在def main 或其他东西中。
    猜你喜欢
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多