Почему делает этот явный вызов метода Scala, позволяют этому быть неявно разрешенным?

Почему это кодирует сбой для компиляции, но компиляции успешно, когда я некомментирую обозначенную строку? (Я использую Scala 2.8 ночью). Это кажется этим явно вызов string2Wrapper позволяет этому использоваться неявно от той точки на.

class A {
  import Implicits.string2Wrapper
  def foo() {
     //string2Wrapper("A") ==> "B" // <-- uncomment
  } 
  def bar() {
    "A" ==> "B"
    "B" ==> "C"
    "C" ==> "D"
  }
  object Implicits {
    implicit def string2Wrapper(s: String) = new Wrapper(s)
    class Wrapper(s: String) {
      def ==>(s2: String) {}
    }
  }
}

Править: спасибо за ответы до сих пор, которые включают указатель на комментарий Martin Odersky,

"Неявное преобразование без явного типа результата видимо только в тексте после его собственного определения. Тем путем мы избегаем циклических ссылочных ошибок".

Я все еще интересовался бы обнаружением 1) какова опасность "циклических ссылочных ошибок"? и 2) Почему явный вызов имеет какое-либо значение?

16
задан Matt R 29 April 2010 в 09:21
поделиться

3 ответа

Явное приписывание типа возвращаемого значения string2Wrapper устраняет проблему.

class A {
  import Implicits._

  def bar() {    
    "A" ==> "B"
    "B" ==> "C"
    "C" ==> "D"
  }
  object Implicits {
    implicit def string2Wrapper(s: String): Wrapper = new Wrapper(s)
    class Wrapper(s: String) {
      def ==>(s2: String) {}
    }
  }
}

Определение Имплицитов перед bar также работает:

class A {
  object Implicits {
    implicit def string2Wrapper(s: String) = new Wrapper(s)
    class Wrapper(s: String) {
      def ==>(s2: String) {}
    }
  }

  import Implicits._

  def bar() {    
    "A" ==> "B"
    "B" ==> "C"
    "C" ==> "D"
  } 
}

Если вам нужно полагаться на неявное преобразование, определенное ниже в текущей области, убедитесь, что вы аннотировали его возвращаемый тип. Совершенно уверен, что это уже появлялось в списках рассылки и может быть ожидаемым поведением, а не ошибкой. Но в настоящий момент я не могу его найти. Я предполагаю, что явный вызов в foo запускает вывод типа возвращаемого типа bar , который затем действителен при вводе содержимого bar .

ОБНОВЛЕНИЕ

В чем опасность ошибки циклического задания?

Тело неявного метода может вызывать метод, требующий неявного преобразования. Если у обоих из них есть предполагаемый тип возврата, вы в тупике. Это не относится к вашему примеру, но компилятор не пытается это обнаружить.

Почему явный вызов имеет значение?

Явный вызов ранее запускает вывод типа возвращаемого типа неявного метода. Вот логика в Implicits.isValid

sym.isInitialized ||
      sym.sourceFile == null ||
      (sym.sourceFile ne context.unit.source.file) || 
      hasExplicitResultType(sym) ||
      comesBefore(sym, context.owner)

UPDATE 2

Эта недавняя ошибка выглядит актуальной: https://lampsvn.epfl.ch/trac/scala/ticket/3373

21
ответ дан 30 November 2019 в 16:49
поделиться

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

<console>:11: error: value ==> is not a member of java.lang.String
 Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type
           "A" ==> "B"
           ^
<console>:12: error: value ==> is not a member of java.lang.String
 Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type
           "B" ==> "C"
           ^
<console>:13: error: value ==> is not a member of java.lang.String
 Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type
           "C" ==> "D"
           ^
12
ответ дан 30 November 2019 в 16:49
поделиться

Если сначала поставить объект Implicits , это сработает. Мне это кажется ошибкой в ​​логике выполнения нескольких проходов компилятора; он предполагает, что может обойтись, не зная о string2Wrapper при компиляции bar . Я предполагаю, что если вы его используете, он знает, что не может уйти, не зная, что такое string2Wrapper на самом деле, на самом деле компилирует Implicits , а затем понимает, что ==> неявно определено в String.

Редактировать: Судя по тому, что опубликовал Retronym, возможно, это «особенность», а не ошибка. Мне все еще кажется странным!

3
ответ дан 30 November 2019 в 16:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: