Подтвердить что ты не робот

Что означает "Перемещение ссылки на определение значения" в Scala?

Я продолжаю получать

Forward reference extends over definition of value a

при попытке скомпилировать мое приложение (внутри SBT).

a просто val a = "", ошибка запускается путем доступа к определенному параметру (функции) непосредственно перед определением a. Параметр имеет тип простого класса case со всеми тремя полями типа Option[...] (2 из Option[org.joda.time.DateTime] и 1 опциона значения перечисления).

Что может означать "Пересылка ссылки на определение значения" вообще и какими могут быть способы борьбы с ней?

4b9b3361

Ответ 1

В зависимости от вашей версии скаляса были ошибки, при которых синтетические методы вызывают эту ошибку.

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

Сообщение об ошибке означает, что у вас есть прямая ссылка на метод, то есть вы вызываете метод до его определения и что определение значения x появляется между этой прямой ссылкой и определением метода, Допустимо иметь прямые ссылки, если нет определения значения между ссылкой и указанным методом.

Ответ 3

Если он ссылается где-то, и scalac запутан с последовательностью, делая его ленивым, можно сделать трюк

Я предполагаю, что это может быть поздно для ответа, и поскольку я не вижу, что вы на самом деле пытаетесь сделать, я не уверен, что это решает его.

Ответ 4

В основном это ошибка.

Исправление состоит в том, чтобы объявить метод перед его вызовом. Я не знаю, почему.

def a(input: String){

}

val k = a("ravi")

Ответ 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 не удалось найти ссылку на метод, который вызывается в вашем методе. Обычно это происходит, когда вы пытаетесь выполнить метод, и реализация вызванного метода выполняется после вызова метода.

как для ex:

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 _)