【问题标题】:Scala error: "forward reference extends over definition of value" when code appears in a functionScala错误:当代码出现在函数中时“前向引用扩展了值的定义”
【发布时间】:2016-05-08 19:17:12
【问题描述】:

我正在尝试使用 Scala 2.11.7 编译以下代码。

object LucasSeq {
  val fibo: Stream[Int] = 0 #:: 1 #:: fibo.zip(fibo.tail).map { pair =>
    pair._1 + pair._2
  }

  def firstKind(p: Int, q: Int): Stream[Int] = {
    val lucas: Stream[Int] = 0 #:: 1 #:: lucas.zip(lucas.tail).map { pair =>
      p * pair._2 - q * pair._1
    }
    lucas
  }
}

fibo 基于Fibonacci sequence example in Scala's Stream documentation,并且可以正常工作。

但是,firstKind 函数尝试使用参数pq 泛化序列(生成Lucas sequences of the first kind),出现以下错误:

LucasSeq.scala:7: error: forward reference extends over definition of value lucas
    val lucas: Stream[Int] = 0 #:: 1 #:: lucas.zip(lucas.tail).map { pair =>
                                         ^
one error found

基本上都是一样的代码,那为什么在函数外却在函数内不行呢?


这个错误信息让我之前的许多程序员感到困惑。我考虑过……

我可能会继续阅读几个小时,但我认为此时最好寻求帮助。我正在寻找解决方案和解释。 (我熟悉函数式编程,但对 Scala 很陌生,所以如果解释涉及“综合”和“隐式”等术语,那么我可能还需要对此进行额外解释。)

【问题讨论】:

  • “使用 -Xprint:typer 诊断进行编译——不确定如何处理这些信息。”请在此处粘贴。
  • @Jus12 粘贴输出有什么意义吗?任何拥有 Scala 编译器的人都可以通过编译上面的代码来重现它。

标签: scala compiler-errors lazy-sequences forward-reference


【解决方案1】:

这里有一个答案,但由于某种原因被删除了。

基本上有两种选择。你可以把你的val 变成lazy val。或者您可以在一个类中将您的lucas: Stream[Int] 定义为一个字段。您可以在构造函数中使用pq 对类进行参数化。

您说得对,原始代码是惰性的。但是 scala 翻译它还不够懒惰。

为了简单起见,想想val a = 1 + a 将被翻译什么代码(我知道代码没有多大意义)。在 Java 中 int a = 1 + a 不起作用。 Java 将尝试在1 + a 中使用a,但a 尚未初始化。即使Java有Integer a = 1 + a,并且a是一个引用,Java仍然不能执行这个,因为Java在分配a时运行1 + a语句

所以它给我们留下了两个选择。将a 定义为不是一个变量,而是一个字段。 Scala 通过定义递归方法而不是字段来自动解决问题 - 因为 scala 中的字段无论如何都是两个方法 + 变量。或者你可以明确地告诉 scala 它应该通过将你的 val 指定为 lazy val 来解决这里的惰性问题。这将使 scala 生成一个隐藏类,其中包含所有必要的基础设施,使其变得懒惰。

您可以通过使用-print 选项运行编译器来检查此行为。但输出相当复杂,尤其是在 lazy val 的情况下。

另外请注意,由于您的流离开了范围,并且还因为您的流有两个参数 - pq,如果您使用 lazy val 选项,则每次调用都会重新计算您的流。如果您选择创建一个额外的类 - 您可以通过为每个可能的 pq 缓存此类的所有实例来控制它

附:我在这里说Java 当然是指JVM。用 Java 来思考更容易

【讨论】:

    猜你喜欢
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 2011-10-15
    相关资源
    最近更新 更多