皆さん、私は次のマップと構造タイプを定義しました:
type Mergeable = { def mergeFrom(data: Array[Byte]): com.google.protobuf.GeneratedMessageLite }
val dispatchMap = Map(
1 -> (ZombieSighting.defaultInstance.asInstanceOf[Mergeable], "akka://UlyssesAgenda/user/ServerCore/DispatchTarget")
)
基本的に、私が行っているのは、「protobufメッセージタイプ1をネットワークから読み取ったときに、バイトからZombieSightingを作成し、指定された文字列で見つかったアクターにディスパッチする」というマップを定義することです。
つまり、これは私が今日持っているコードであり、メッセージとアクターを作成し、メッセージをアクターに送信します。
val dispatchInfo = dispatchMap.get(messageType)
val theMessage = dispatchInfo.map { _._1.mergeFrom(theBytes) }.get
val actorPath = dispatchInfo.map { _._2 }
val targetActor = actorPath.map { SocketServer.system.actorFor(_) }
targetActor.map { _ ! theMessage }
私がこれを見るとき、私が考えることができるのは、これがどのように機能しないプログラミングの行数であるかということだけであり、これを行うためのはるかにエレガントな方法があると思わずにはいられません。タプルをパラメーターとして受け取り、変更されたタプルを返す関数を記述できることは知っていますが、ここでは、クリーンな慣用的なスカラに関して何も買わないと思います。
私の直感では、「dispatchMap.get(messageType)」で実行できる単一のマップステートメントがあり、tuple._2に基づくAkkaアクターのインスタンスと、tuple._1に基づくマージされたprotobufオブジェクトが得られます。
誰かがこのコードをポン引きして行数を減らし、より機能的にする方法を提案できますか?例えば
val (targetActor, theMessage) = ????
targetActor ! theMessage
編集:これがリファクタリングの私の最初の試みです..これはそれを行うための「スカラの方法」ですか?
val (msg, actor) = dispatchMap.get(messageType).map {
case (m:Mergeable, path:String) =>
(m.mergeFrom(theBytes), SocketServer.system.actorFor(path) )
}.get
actor ! msg
編集2:以下のコメント投稿者が提案したバージョンですが、これが本当に慣用的なものかどうかはわかりません。
def dispatchMessage: IO.Iteratee[Unit] =
repeat {
for {
(messageType, byteString) <- readMessage
} yield {
for (
(protoMessage, actorPath) <- dispatchMap.get(messageType);
theMessage = protoMessage.mergeFrom(byteString.toArray);
targetActor = SocketServer.system.actorFor(actorPath) )
yield
targetActor ! theMessage
}
}
?