私はkafka-streamsライブラリ用のScalaラッパーを作成しています。基本的なアプローチは、KStream
のようなkafka-streamsクラスから暗黙の変換を提供して、豊富なKStreamOps
クラスにすることです。ScalaはJava 8 Lambdaへの暗黙的な変換を優先させることができますか?
たとえば、KStream
は以下map
署名を提供する:KeyValueMapper
は(Scalaの観点から)署名付きSAM (K, V) => KeyValue[K1, V1]
ある
<K1, V1> KStream<K1, V1> map(KeyValueMapper<K, V, KeyValue<K1, V1>> mapper)
。ここmap
は、ユーザーが「doesnのようにkafka-streams
固有KeyValue
型にそれを変換Tuple2
とハンドルを返す関数を期待していること
class KStreamOps[K, V](underlying: KStream[K, V]) {
def map[K1, V1](f: (K, V) => (K1, V1)): KStream[K1, V1] =
underlying.map { (k, v) =>
val tuple = f(k, v)
KeyValue.pair(tuple._1, tuple._2)
}
}
は注意:ここで
はmap
方法を提供するKStreamOps
の最小限の実装です直接KeyValue
と対話する必要があります。
私は暗黙の型変換を提供:
implicit def ops[K, V](kstream: KStream[K, V]): KStreamOps[K, V] = new KStreamOps[K, V](kstream)
をしかし、私は次のようなコードで私の新しいmap
を使用しようとすると:
val inputStream: KStream[Int, String] = builder.stream(inputTopic)
stream.map{ (k, v) => (k, v) }
私は、次のコンパイルエラーが表示されます。
[error] KStreamOpsTest.scala:47: type mismatch;
[error] found : (Int, String)
[error] required: org.apache.kafka.streams.KeyValue[Int,String]
[error] stream.map((k, v) => (k, v))
[error] ^
[error] KStreamOpsTest.scala:47: Could not derive subclass of org.apache.kafka.streams.kstream.KeyValueMapper[Int,String,org.apache.kafka.streams.KeyValue[Int,String]]
[error] (with SAM `def method apply(x$1: Int, x$2: String)org.apache.kafka.streams.KeyValue[Int,String]`)
[error] based on: ((k: Int, v: String) => scala.Tuple2(k, v)).
[error] stream.map((k, v) => (k, v))
したがって、コンパイラはを使用しようとしています関数の出力がTuple2
であると予想する私のKStreamOps#map
の代わりに、KeyValue
が返されると予想されるSAMを使用して、を返します。
私のメソッドの名前をKStreamOps#map1
に変更し、stream.map1
を呼び出すと、暗黙の変換が期待通りに機能し、コードがコンパイルされます。
コンパイラは、正しいシグネチャの機能を持つメソッドを取得する暗黙の変換が存在することをコンパイラが認識できないのはなぜですか?関数の戻り値の型は考慮されていませんか? SAMはいつも勝つだろうか?
私はこれをScala 2.11.8で、-Xexperimental
フラグをオンにしてテストしています。
コンパイラは、元のオブジェクトにそのようなメソッドが既に存在する場合、 'map'メソッドを持つものへの暗黙的な変換を探しません。これは単にアルゴリズムがどのように機能するかです。暗黙のうちに明示的に作成された独自のラッパークラスの名前変更や作成を除いて、これを回避する方法は不明です。 –
メソッドシグネチャの一意性を決定する要素をより完全に理解したいと思います。私は 'map'メソッドが、1つではなく2つの引数をとると仮定します。たとえば、既存の' map'メソッドと混同しないで暗黙の変換を探します。私はまた、非関数型を取る 'map(x:Int)'が別個であると仮定します。本当?ここでの特定の問題は、型が消去されているか、シグネチャが 'map(f:Function)'にコンパイルされているため、関数のパラメータと戻り値の型を区別できないのでしょうか? –