在Scala中,“Forward reference extends over definition of value”是什么意思?

wgx48brx  于 9个月前  发布在  Scala
关注(0)|答案(9)|浏览(225)

我不断收到

Forward reference extends over definition of value a

错误,而试图编译我的应用程序(内部SBT)。
a只是val a = "",错误是通过访问a定义之前的特定参数(函数)触发的。该参数是一个简单的case类类型,所有三个字段都是Option[...]类型(2个是Option[org.joda.time.DateTime],1个是枚举值的Option)。
"前向引用扩展到值的定义"到底意味着什么?有什么方法可以克服它?

pbgvytdp

pbgvytdp1#

错误消息意味着你有一个方法的前向引用,即。你在定义一个方法之前就调用了它,值x的定义出现在前向引用和方法定义之间。只有在引用和被引用的方法定义之间没有值定义的情况下,前向引用才是法律的。

u7up0aaq

u7up0aaq2#

基本上是个bug。
修复方法是在调用方法之前声明它。我不知道为什么

def a(input: String){

}

val k = a("ravi")
3htmauhk

3htmauhk3#

根据你的scalac版本,有一些bug是合成方法导致的。
https://issues.scala-lang.org/browse/SI-6278
假设f是这样生成的:

object Test {
  def main(args: Array[String]) {
    class NotUsed {val x = f}
    val dummy = false
    def f = true
  }
}

Case类、默认参数和隐式类都涉及到合成。
在该ticket的示例代码(已修复)中,您可以通过将implicit移动到函数的末尾来中断ok方法:

object tiny {

  def main(args: Array[String]) {
    ok(); nope()
  }
  def ok() {
    class Foo(val i: Int) {
      def foo[A](body: =>A): A = body
    }
    implicit def toFoo(i: Int): Foo = new Foo(i)

    val k = 1
    k foo println("k?")
    val j = 2
  }
  def nope() {
    implicit class Foo(val i: Int) {
      def foo[A](body: =>A): A = body
    }

    val k = 1
    k foo println("k?")
    //lazy
    val j = 2
  }
}

有什么方法可以对抗它?
正如代码中的注解所暗示的那样,使定义懒惰是一种解决方法。
例2,假设函数很长,你没有注意到命名问题:

object Test {
  def main(args: Array[String]) {
    class NotUsed {val xs = args}
    val dummy = false
    // oops, shadows the parameter
    def args = Seq("a","b","c")
  }
}
qoefvg9y

qoefvg9y4#

如果它被引用到某个地方,而scalac与序列混淆了,那么让它变懒就可以做到这一点
我想这可能是一个答案太晚了,因为我看不到你实际上想做什么,我不确定这是否解决了它。

gt0wga4j

gt0wga4j5#

一个由sepp 2k给出的答案的例子

object ForwardReferenceTest {

  def main(args: Array[String]): Unit = {
    test
    val x = 1
    def test = println("hi")
  }
}

你会得到错误

Error:(7, 5) forward reference extends over definition of value x
    test
    ^

在调用之后定义函数test,并且在其间存在x的值定义。删除/移动val x定义将解决问题。

x9ybnkn6

x9ybnkn66#

这条消息意味着在运行时scala无法找到你的方法中调用的方法的引用。当你试图调用一个方法,而被调用方法的实现在调用方法之后时,通常会发生这种情况。
例如:

implicit val userDetails: Reads[UserDetails] = (
          (JsPath \ "name").read[String] and
            (JsPath \ "providers").read[List[Provider]]
          )(UserDetails.apply _) 

implicit val providers: Reads[Provider] = (
          (JsPath \ "providerName").read[String] and
            (JsPath \ "providerUserId").read[String] and
            (JsPath \ "authtoken").read[String]
          )(Provider.apply _)

以及正确的方法

implicit val providers: Reads[Provider] = (
      (JsPath \ "providerName").read[String] and
        (JsPath \ "providerUserId").read[String] and
        (JsPath \ "authtoken").read[String]
      )(Provider.apply _)

     implicit val userDetails: Reads[UserDetails] = (
      (JsPath \ "name").read[String] and
        (JsPath \ "providers").read[List[Provider]]
      )(UserDetails.apply _)
kmpatx3s

kmpatx3s7#

你应该检查你的进口。它必须从导入中导入变量名,该变量名必须在导入到代码中的某些库中使用。删除导入。

bpsygsoo

bpsygsoo8#

在我的例子中,将瓦尔定义移到隐式瓦尔定义之后就足够了,不清楚为什么。分配给瓦尔定义的方法实际上是在实际调用它的方法之前定义的。

fkaflof6

fkaflof69#

当我们在定义变量之前引用它时,就会发生这种错误。如错误所述,它是正向引用。

相关问题