2016-04-24 30 views
2

Scala関数(おそらく匿名)から暗黙的な変換をjava.util.function.Functionに作成したいと考えています。ここで私が持っているものです。Scala関数からJava関数への暗黙的変換

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コンパイラは3番目のケースでパラメータの型を推測できないのですか?
  • タイプが推測されるように暗黙の変換を変更できますか?

私はrelated questionを認識していますが、私の質問には答えられません。

この問題は、Javaとの相互運用性、btwには関係していないようです。 JavaFunctionをカスタムScala特性に置き換えると、動作は変わりません。

+0

[関連の記事](http://www.tikalk.com/incubator/simulating-sam-closures-scala/)が見つかりました。これは答えを提供するものではありませんが、Scala関数の暗黙的な変換の関連トピックに触れています。 – Mifeet

答えて

3

なぜ、Scalaコンパイラは3番目のケースでパラメータの型を推論できませんか?

ラムダ式のパラメータ(複数も可)のタイプ(複数可)を推測するために、期待タイプ(この場合)String => ?なければなりません。 converted3では、予想されるタイプはJavaFunction[String, Int]です。これはScala関数ではないため、動作しません。 Scala 2.12では-Xexperimental scalac optionでは2.11になります。これはthe specificationに従う:

匿名関数の期待される型形状scala.Functionn [S1、...、Snの、R]である、またはそのような関数型にSAM-変換できる場合、 のSiが予想タイプに定義されているパラメータ XIの種類 のTiは限り、省略することができ、そして は、Ti = のSiを想定しています。関数リテラルには、予想されるタイプが存在しない場合はさらに、タイプ 電子 をチェックし、予想されるタイプはR.

で、Tiは明示的に指定する必要があり、すべての仮パラメータ型、およびEの予想タイプが定義されていません。

「SAM-変換」の部分は、デフォルトでは2.11に-Xexperimental /2.12はなく、有効なによって活性化です。

タイプが推論されるように暗黙の変換を変更できますか?

私はそう信じません。何ですかすることができます doは場所の変換が起こるのを変更することです:val unconverted: String => Int = s => s.toInt(またはちょうどval unconverted = (s: String) => s.toInt)を書き、JavaFunction[String, Int]が期待されるところでそれを渡してください。

+0

ご返信ありがとうございます。期待される型が 'String =>?'でなければならない理由についての参考文献を提供してください。 – Mifeet

+0

@Mifeet編集を参照してください。 –

+0

ありがとう、それは私が探していたものです。 – Mifeet

1

val foo: SomeType = barと書くと、コンパイラは割り当てが有効であることを「証明」する方法を探しています。 barには、SomeType(または明らかにSomeType自体)のサブクラスであるタイプがあります。または、barのタイプからSomeTypeに暗黙的に変換されているタイプのいずれかがあります。 どちらの場合も、yoyが理解できるように、助けを求めるにはbarのタイプを知っていなければなりません。しかし、val converted3: JavaFunction[String, Int] = s => s.toIntと書くと、右辺の型は定義されません。コンパイラーは、それがある関数であることを知っています.Inを返しますが、引数の型がなければ、それだけでは不十分です。

コンパイラが範囲内の暗黙的な変換をすべてチェックせず、LHSと互換性のある何かを返すことは、変換を使用するためには入力型を知る必要があるということです。

AFAIKの周りに暗黙の変換を使用できるようにするには、一方向または他の形式のrhsを定義する必要があります。

+0

ありがとうございます。私は、バーのタイプを知っておかなければならないという声明に完全に同意するわけではありません。例えば。 '' val'':Function1 [String、Int] = s => s.toInt'において、 's'が' String'であることを明示せずにRHSの型が推論されます。 – Mifeet

+0

@Mifeetこの場合、暗黙の変換が含まれていないので、rhsの型は 'Function1 [String、Int]'であることが知られています。だから、私が言ったことは:rhsのタイプは知られていなければなりません。 – Dima

+0

「匿名関数の予想される型」がわかっている場合、私は同意します。しかし、RHSのタイプは、「Function1 [String、Int]」である必要はなく、例えば、「Function1 [Object、Int]」とすることができる。私はそれらが微妙な違いであることを知っています。 – Mifeet

関連する問題