【问题标题】:What does "Forward reference extends over definition of value" mean in Scala?Scala中的“前向引用扩展了值的定义”是什么意思?
【发布时间】:2012-11-11 04:09:46
【问题描述】:

我不断得到

Forward reference extends over definition of value a

尝试编译我的应用程序时出错(在 SBT 中)。

a 只是val a = "",错误是通过在a 定义之前访问(函数的)特定参数触发的。参数是一个简单的case类类型,所有三个字段都是Option[...]类型(Option[org.joda.time.DateTime]的2个和枚举值Option的1个)。

“前向引用扩展了价值的定义”到底意味着什么?有什么方法可以对抗它?

【问题讨论】:

    标签: scala


    【解决方案1】:

    错误消息意味着您有一个方法的前向引用,即您在定义它之前调用了一个方法,并且值 x 的定义出现在该前向引用和方法的定义之间.只有在引用和被引用的方法定义之间没有值定义时,前向引用才是合法的。

    【讨论】:

    • 你能提供一个有效的前向引用的例子吗?
    • 魔术,我重新安排了我的方法,编译错误消失了
    【解决方案2】:

    基本上这是一个错误。

    解决方法是在调用方法之前声明它。我不知道为什么。

    def a(input: String){
    
    }
    
    val k = a("ravi")
    

    【讨论】:

    • 或者让值变得懒惰
    【解决方案3】:

    根据您的 scalac 版本,存在合成方法导致此错误的错误。

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

    案例类、默认参数和隐式类涉及合成。

    在该票证的示例代码(已修复)中,您可以通过将隐式移到函数末尾来破坏 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")
      }
    }
    

    【讨论】:

    • “影响版本/s:未发布-2.10.x,修复版本/s:未发布-2.10.x” - 它说。即使在 2.10RC2 中,该错误在任何已发布版本中都未修复,我是否理解正确?
    • 确实如此。我刚刚尝试了 2.10RC2,但问题仍然存在...... :-(
    • 我什至将该类设为裸类(不是案例类)并从中删除了所有参数默认值,但我仍然收到错误消息。我的情况要简单得多——我只是尝试访问一个方法参数,它会触发错误。我还是不明白这个特殊参数有什么特别之处。
    • 为什么不粘贴示例以便我们特别看到?它也可以帮助使用 -Xprint:typer(或有时在 typer 之后的一个阶段)。
    • 我找到了实际问题的原因(感谢 IntelliJ Idea 在您按住 Ctrl 并将鼠标悬停在值使用上时显示值声明)!稍后在同一函数中声明了具有相同名称(如函数参数)的 val。所以这不是编译器错误,这是我的错误。
    【解决方案4】:

    如果它在某处被引用并且 scalac 与序列混淆,让它变得懒惰可以解决问题

    我想答案可能为时已晚,而且由于我看不到您实际尝试做什么,因此我不确定这是否可以解决问题。

    【讨论】:

      【解决方案5】:

      sepp2k给出的答案示例

      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 定义将解决问题。

      【讨论】:

        【解决方案6】:

        该消息意味着在运行时 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 _)
        

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            在我的情况下,将 val 定义移到隐式 val 定义之后就足够了,不清楚原因。分配给 val 定义的方法实际上是在实际调用它的方法之前定义的。

            【讨论】:

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