在定义函数之前调用函数(前向引用扩展到变量的定义)

cor*_*zza 1 compiler-construction variables scope scala function

考虑这个基本的Scala示例代码:

object Test {
    def main(args: Array[String]) {
        inner()

        var x: Int = 5

        def inner() {
            println("x: " + x)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

尝试编译它会产生以下错误消息:

test.scala:3: error: forward reference extends over definition of variable x
        inner()
        ^
one error found
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 在这种情况下什么是前向引用,它对"扩展变量x的定义"意味着什么?
  2. 为什么前面的代码会引发这个编译时错误?
  3. 这个错误是怎么来的?好像编译器必须实现一些类似解释器的功能并遵循函数调用!

这个问题并不是关于定义的顺序,而是确切地调用函数的时候.在定义函数之前调用函数是完全合法的 - 但如果在调用和函数定义之间放置一个变量,并且函数使用此变量,它就会突然变为非法.

我想解释这个语言功能!为什么会这样?它是如何工作的?是否还有其他更复杂的例子 - 即它只是某些其他功能的一部分还是某些规则的结果?

我想象编译器目前在做什么:

  1. 检查函数是否是可以访问当前作用域变量的闭包,
  2. 检查它是否确实访问当前范围中的变量,并且
  3. 对于闭包访问的每个变量,检查变量是否在调用之前定义

我基本上回答了我的第三个问题吗?这是这种行为的工作原理吗?它似乎使编译器复杂化(特别是如果我们考虑具有多级函数的情况).

如果是这种情况,它如何融入语言的正式定义,即语法?在我看来,我写的程序在语法上是正确的.

Vic*_*roz 5

来自http://www.scala-lang.org/docu/files/ScalaReference.pdf:

声明或定义引入的名称范围是包含绑定的整个语句序列.然而,块中的前向引用存在限制:在语句序列s1 ... sn中构成块,如果si中的简单名称是指由sj定义的实体,其中j> = i,那么对于所有sk之间的sk包括si和sj,

•sk不能是变量定义.

•如果sk是一个值定义,它必须是懒惰的