Вывод типа в списке аргументов в сочетании с не работающим сеттером
Давайте представим следующие предметы по объему:
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
параметр типа, потому что он исходит из аргумента функции.