我一直在
Forward reference extends over definition of value a
尝试编译我的应用程序时(在SBT内)错误。
a
只是val a = ""
,错误是通过在a
定义之前访问(函数的)特定参数来触发的。该参数是一个简单的case类类型,其中包含Option[...]
类型的所有三个字段(Option[org.joda.time.DateTime]
中的2个和枚举值中的1个选项)。
什么可以“转发参考延伸超过价值的定义”意味着什么,以及可以采取什么方式来对抗它?
答案 0 :(得分:44)
错误消息表示您有一个方法的前向引用,即您在定义方法之前调用方法,并且值x
的定义出现在该前向引用和定义之间方法。如果引用和引用的方法定义之间没有值定义,则只有前向引用才是合法的。
答案 1 :(得分:12)
根据您的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")
}
}
答案 2 :(得分:9)
如果在某处引用它并且scalac与序列混淆,那么使它变得懒惰可以做到这一点
我想可能会迟到一个答案,因为我看不到你实际上想要做什么,我不确定是否能解决它。
答案 3 :(得分:8)
基本上它是一个错误。
修复方法是在调用方法之前声明方法。我不知道为什么。
def a(input: String){
}
val k = a("ravi")
答案 4 :(得分:1)
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
定义将解决问题。
答案 5 :(得分:1)
该消息表示在运行时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 _)
答案 6 :(得分:0)
您应该检查您的进口。 它必须是从导入中导入变量名, 变量名必须在导入到您的代码中的某些库中使用。 删除导入。