我想创建一个从Scala函数(可能是匿名的)到java.util.function.Function
的隐式转换。这就是我所拥有的:
import java.util.function.{Function => JavaFunction}
implicit def scalaFunctionToJavaFunction[From, To](function: (From) => To): JavaFunction[From, To] = {
new java.util.function.Function[From, To] {
override def apply(input: From): To = function(input)
}
}
除了当被转换的函数没有明确指定参数类型时类型推断失败时,它工作正常:
val converted: JavaFunction[String, Int] = (s: String) => s.toInt // works fine
val converted2: JavaFunction[String, Int] = scalaFunctionToJavaFunction(s => s.toInt) // works
val converted3: JavaFunction[String, Int] = s => s.toInt // gives compilation error "missing parameter type"
编译器能够推断出类型
我的问题是:
我知道有related question涉及此主题,但没有回答我的问题。
这个问题似乎与Java的互操作性无关,顺便说一句。如果我用自定义Scala特征替换JavaFunction
,行为将保持不变。
答案 0 :(得分:3)
为什么Scala编译器在第三种情况下不能推断出参数的类型?
要推断lambda表达式的参数类型,期望类型必须是String => ?
(对于这种情况)。在converted3
中,预期类型为JavaFunction[String, Int]
。这不是Scala函数,所以它不会起作用。它将在Scala 2.12中,或在2.11中与-Xexperimental
scalac option。这是根据the specification:
" SAM转换" part是由如果匿名函数的预期类型是scala.Functionn [S1,...,Sn,R]形状,或者可以SAM转换为这样的函数类型,则类型 钛 一个参数 喜 可以省略,至于 硅 在预期的类型中定义,和 钛 = 硅 假设。此外,类型检查时的预期类型 Ë 是 R上。
如果函数文字没有预期的类型,则必须显式指定所有形式参数类型Ti,并且未定义e的预期类型。
-Xexperimental
/ 2.12激活的,默认情况下在2.11中无效。
我可以修改隐式转换,以便推断出类型吗?
我不相信。您可以做的是更改地点转换:写val unconverted: String => Int = s => s.toInt
(或只是val unconverted = (s: String) => s.toInt
)并将其传递到预期JavaFunction[String, Int]
的位置。
答案 1 :(得分:1)
当你编写val foo: SomeType = bar
时,编译器正在寻找一种“证明”的方法,即赋值是有效的。这可以通过以下两种方式之一来证明:bar
有一个类型,它是SomeType
的子类(或显然是SomeType
本身)或者是任何类型的隐式转换{ {1}}是bar
。
正如你可以看到的那样,在两种情况下,对于工作的辅助,必须知道SomeType
的类型。但是当你写bar
时,右边的类型没有定义。编译器知道它是一些函数,返回一个Int,但没有参数类型,这还不够。
另一种方式是说编译器不会检查范围内的每个隐式转换,返回与LHS兼容的东西,为了使用转换,它需要知道输入类型。
AFAIK无法绕过它,你必须以某种方式定义rhs的类型才能使用隐式转换。