type inference in argument list in combination with setter not working
Let's imagine the following items in scope:
object Thing {
var data: Box[String] = Empty
}
def perform[T](setter: Box[T] => Unit) {
// doesn't matter
}
The following fails to compile:
perform(Thing.data = _)
The error message is:
<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 = _)
^
While the following compiles:
perform(Thing.data_=)
I have since surpassed this issue by creating a better abstraction, but my curiosity still remains.
Can anyone explain why this is?
Let's expand out what you're doing in the first example:
Thing.data = _
is shorthand for defining an anonymous function, which looks like:
def anon[T](x: Box[T]) {
Thing.data = x
}
So when you call
perform(Thing.data = _)
it's the same as
perform(anon)
The problem is anon
and perform
take a type parameter T
and at no point are you declaring what T
is. The compiler can only infer type parameters in a function call from passed arguments, not from within the function body, so it cannot infer in anon
that T
should be String
.
Notice that if you call
perform[String](Thing.data = _)
the compiler has no issue because it now knows what T
should be, and if you try to use any type besides string, you'll get a type mismatch error, but the error occurs in the body of the anonymous function, not on the call to perform
.
However, when you call
perform(Thing.data_=)
you are passing the method Thing.data_=
, which is explicitly defined as Box[String] => Unit
, so the compiler can infer perform
's type parameter because it is coming from a function argument.