I would like to create an implicit conversion from a Scala function (possibly anonymous) to java.util.function.Function
. Here is what I have:
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)
}
}
It works fine except that the type inference fails when the function being converted doesn't specify parameter type explicitly:
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"
The compiler is able to infer the type
My questions are:
I'm aware of a related question which touches on this subject but doesn't give an answer to my questions.
The problem doesn't seem to be related to interoperability with Java, btw. If I replace JavaFunction
with a custom Scala trait, the behavior remains the same.
Why cannot Scala compiler infer type of the parameter in the third case?
To infer type(s) of parameter(s) of a lambda-expression, the expected type must be String => ?
(for this case). In converted3
, the expected type is JavaFunction[String, Int]
. This isn't a Scala function, so it won't work. It will in Scala 2.12, or in 2.11 with -Xexperimental
scalac option. This is according to the specification:
If the expected type of the anonymous function is of the shape scala.Functionn[S1,…,Sn, R], or can be SAM-converted to such a function type, the type Ti of a parameter xi can be omitted, as far as Si is defined in the expected type, and Ti = Si is assumed. Furthermore, the expected type when type checking e is R.
If there is no expected type for the function literal, all formal parameter types Ti must be specified explicitly, and the expected type of e is undefined.
The "SAM-converted" part is the one activated by -Xexperimental
/2.12 and not valid in 2.11 by default.
Can I modify the implicit conversion so that the type gets inferred?
I don't believe so. What you can do is to change the place conversion happens: write val unconverted: String => Int = s => s.toInt
(or just val unconverted = (s: String) => s.toInt
) and pass it where JavaFunction[String, Int]
is expected.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments