参数列表中的类型推断与setter不起作用

Sco*_*bie 7 functional-programming scala type-inference anonymous-function

让我们想象一下范围内的以下项目:

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

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

以下无法编译:

perform(Thing.data = _)
Run Code Online (Sandbox Code Playgroud)

错误消息是:

<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 = _)
                                 ^
Run Code Online (Sandbox Code Playgroud)

以下编译:

perform(Thing.data_=)
Run Code Online (Sandbox Code Playgroud)

我已经通过创造更好的抽象来超越这个问题,但我的好奇心仍然存在.

谁能解释为什么会这样?

Dan*_*mon 3

让我们扩展一下您在第一个示例中所做的事情:

Thing.data = _
Run Code Online (Sandbox Code Playgroud)

是定义匿名函数的简写,如下所示:

def anon[T](x: Box[T]) {
  Thing.data = x
}
Run Code Online (Sandbox Code Playgroud)

所以当你打电话时

perform(Thing.data = _)
Run Code Online (Sandbox Code Playgroud)

它是一样的

perform(anon)
Run Code Online (Sandbox Code Playgroud)

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 = _)
Run Code Online (Sandbox Code Playgroud)

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_=)
Run Code Online (Sandbox Code Playgroud)

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.