Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion from Scala function to Java Function

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:

  • Why cannot Scala compiler infer type of the parameter in the third case?
  • Can I modify the implicit conversion so that the type gets inferred?

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.

like image 364
Mifeet Avatar asked Feb 17 '26 22:02

Mifeet


1 Answers

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.

like image 184
Alexey Romanov Avatar answered Feb 19 '26 12:02

Alexey Romanov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!