Вывод типа в списке аргументов в сочетании с не работающим сеттером

Давайте представим следующие предметы по объему:

object Thing { 
  var data: Box[String] = Empty
}

def perform[T](setter: Box[T] => Unit) {
  // doesn't matter
}

Следующее не компилируется:

perform(Thing.data = _)

Сообщение об ошибке:

<console>:12: error: missing parameter type for expanded function ((x$1) => Thing.data = x$1)
              perform(Thing.data = _)
                                   ^
<console>:12: warning: a type was inferred to be `Any`; this may indicate a programming error.
              perform(Thing.data = _)
                                 ^

Пока следующие компиляции:

perform(Thing.data_=)

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

Кто-нибудь может объяснить, почему это так?

1 ответ

Решение

Давайте расширим то, что вы делаете в первом примере:

Thing.data = _

является сокращением для определения анонимной функции, которая выглядит следующим образом:

def anon[T](x: Box[T]) {
  Thing.data = x
}

Поэтому, когда вы звоните

perform(Thing.data = _)

это так же, как

perform(anon)

Проблема в anon а также perform принять параметр типа T и ни в коем случае вы не заявляете, что T является. Компилятор может выводить параметры типа в вызове функции только из переданных аргументов, но не из тела функции, поэтому он не может сделать вывод в anon тот T должно быть String,

Обратите внимание, что если вы позвоните

perform[String](Thing.data = _)

у компилятора нет проблем, потому что теперь он знает, что T должно быть, и если вы попытаетесь использовать любой тип, кроме строки, вы получите ошибку несоответствия типов, но ошибка происходит в теле анонимной функции, а не при вызове perform,

Тем не менее, когда вы звоните

perform(Thing.data_=)

вы проходите метод Thing.data_=, который явно определяется как Box[String] => Unitтак что компилятор может сделать вывод performпараметр типа, потому что он исходит из аргумента функции.

Другие вопросы по тегам