从 Scala 函数到 Java 函数的隐式转换
Implicit conversion from Scala function to Java Function
我想创建一个从 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"
编译器能够推断类型
我的问题是:
- 为什么 Scala 编译器无法在第三种情况下推断参数类型?
- 我可以修改隐式转换以便推断类型吗?
我知道一个 涉及到这个主题,但没有回答我的问题。
这个问题似乎与 Java 的互操作性无关,顺便说一句。如果我用自定义 Scala 特征替换 JavaFunction
,行为保持不变。
Why cannot Scala compiler infer type of the parameter in the third case?
要推断 lambda 表达式的参数类型,预期类型 必须是 String => ?
(对于这种情况)。在 converted3
中,期望的类型是 JavaFunction[String, Int]
。这不是一个 Scala 函数,所以它不会工作。它 将 在 Scala 2.12 中,或在 2.11 中 -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.
"SAM-converted"部分是由-Xexperimental
/2.12激活的部分,默认情况下在2.11中无效。
Can I modify the implicit conversion so that the type gets inferred?
我不这么认为。您可以 做的是更改转换发生的位置:写入val unconverted: String => Int = s => s.toInt
(或只是val unconverted = (s: String) => s.toInt
)并将其传递到预期JavaFunction[String, Int]
的位置。
当你写 val foo: SomeType = bar
时,编译器正在寻找一种方法 "prove",以确保赋值有效。这可以通过以下两种方式之一来证明:bar
有一个类型,它是 SomeType
的子类(或者显然是 SomeType
本身),或者存在从任何类型的隐式转换 bar
是 SomeType
。
正如你所看到的,在这两种情况下,为了使 assihnment 起作用,必须知道 bar
的类型。但是当你写 val converted3: JavaFunction[String, Int] = s => s.toInt
时,右侧的类型没有定义。编译器知道,它是某个函数,返回一个 Int,但没有参数类型,这是不够的。
另一种说法是,编译器不会检查范围内的每个隐式转换,返回与 LHS 兼容的内容,为了使用转换,它需要知道输入类型。
没有办法绕过它 AFAIK,您必须以一种或另一种方式定义 rhs 的类型才能使用隐式转换。
我想创建一个从 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"
编译器能够推断类型
我的问题是:
- 为什么 Scala 编译器无法在第三种情况下推断参数类型?
- 我可以修改隐式转换以便推断类型吗?
我知道一个
这个问题似乎与 Java 的互操作性无关,顺便说一句。如果我用自定义 Scala 特征替换 JavaFunction
,行为保持不变。
Why cannot Scala compiler infer type of the parameter in the third case?
要推断 lambda 表达式的参数类型,预期类型 必须是 String => ?
(对于这种情况)。在 converted3
中,期望的类型是 JavaFunction[String, Int]
。这不是一个 Scala 函数,所以它不会工作。它 将 在 Scala 2.12 中,或在 2.11 中 -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.
"SAM-converted"部分是由-Xexperimental
/2.12激活的部分,默认情况下在2.11中无效。
Can I modify the implicit conversion so that the type gets inferred?
我不这么认为。您可以 做的是更改转换发生的位置:写入val unconverted: String => Int = s => s.toInt
(或只是val unconverted = (s: String) => s.toInt
)并将其传递到预期JavaFunction[String, Int]
的位置。
当你写 val foo: SomeType = bar
时,编译器正在寻找一种方法 "prove",以确保赋值有效。这可以通过以下两种方式之一来证明:bar
有一个类型,它是 SomeType
的子类(或者显然是 SomeType
本身),或者存在从任何类型的隐式转换 bar
是 SomeType
。
正如你所看到的,在这两种情况下,为了使 assihnment 起作用,必须知道 bar
的类型。但是当你写 val converted3: JavaFunction[String, Int] = s => s.toInt
时,右侧的类型没有定义。编译器知道,它是某个函数,返回一个 Int,但没有参数类型,这是不够的。
另一种说法是,编译器不会检查范围内的每个隐式转换,返回与 LHS 兼容的内容,为了使用转换,它需要知道输入类型。
没有办法绕过它 AFAIK,您必须以一种或另一种方式定义 rhs 的类型才能使用隐式转换。