Неявные преобразования и параметры по имени целевого типа - PullRequest
1 голос
/ 29 июня 2019

рассмотрим этот код:

class DelayedInt(val value: Int) {
  var locked = true
}

object DelayedInt {
  implicit def delayedIntToInt(del: DelayedInt) = {
    if (del.locked) throw new RuntimeException("not yet!")
    del.value
  }
}

object Main {
  var queue: Seq[() => Int] = Seq.empty

  def queueInt(int: => Int): Unit = {
    queue :+= int _
  }

  def printQueue(): Unit =
    for (f <- queue)
      println("int is: " + f.apply())

  def main(args: Array[String]): Unit = {
    val di = new DelayedInt(42)
    // println(5 + di) // throws exception
    queueInt(5 + di) // OK
    queueInt(di) // OK
    di.locked = false
    printQueue()
  }
}

Класс DelayedInt выдает исключение при преобразовании в int, если только он не разблокирован явно.

Функция println должна завершиться сбоем, посколькуэто вызывает неявное преобразование.

queueInt функция работает нормально, по-видимому, потому что она использует параметры по имени и неявное преобразование не вызывается до printQueue.

Что мне неясно, так это как Scala решаеткогда запустить неявное преобразование?Особенно в случае queueInt(di), он должен каким-то образом выяснить, что результат будет правильного типа, без использования неявного преобразования.

Какие шаги для оценки этого?

Ответы [ 2 ]

2 голосов
/ 29 июня 2019

Что мне неясно, как Scala решает, когда запускать неявное преобразование?

Это не так, напрямую.Он просто вставляет его там, где этого требует ожидаемый тип, поэтому после этой стадии компиляции ваш код становится

val di = new DelayedInt(42)
// println(5 + DelayedInt.delayedIntToInt(di)) // throws exception
queueInt(5 + DelayedInt.delayedIntToInt(di)) // OK
queueInt(DelayedInt.delayedIntToInt(di)) // OK
di.locked = false
printQueue()

, а затем случаи queueInt ведут себя нормально для параметров по имени.

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

Это, конечно, основано на типах и не требует запуска ничего.

2 голосов
/ 29 июня 2019

Насколько я понимаю, в обоих случаях queueInt(5 + di) и queueInt(di) неявное преобразование должно произойти до того, как произойдет какая-либо оценка. queueInt принимает аргумент по имени, а затем из-за синтаксиса int _ добавляет неприменимую функцию к queue: Seq[() => Int], поэтому переданные аргументы не оцениваются после завершения queueInt. Только при вызове printQueue() функции элемента queue могут быть оценены из-за вызова f.apply().

В случае println(5 + di) аргумент не передается по имени, поэтому после неявного преобразования он оценивает до того, как передается в println, следовательно, бросок, но неявное преобразование по-прежнему происходит первым , как и для queueInt случаев.

Кажется, ничего странного здесь не происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...