夥計們, 我有以下的地圖和結構類型定義:慣用斯卡拉 - 元組上執行函數的值
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,並將其發送給在指定字符串中找到的actor。
所以,這是我今天有一個創建一個消息,一個演員的代碼,並且將消息發送到演員:
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 }
當我看到這一點,所有我能想到的是多少這看起來像是非功能性編程的一線,我不禁想到有一種更加優雅的方式來做到這一點。我知道我可以編寫以元組作爲參數並返回修改過的元組的函數,但我認爲在這裏我沒有購買任何干淨的慣用scala。
我的直覺說我可以在「dispatchMap.get(messageType)」上運行一個單獨的map語句,它會給我一個基於tuple._2的Akka actor的實例和一個基於tuple._1的合併protobuf對象。
有人可以建議一種方法來皮條碼這個代碼,並減少行數,使其更多的功能?例如
val (targetActor, theMessage) = ????
targetActor ! theMessage
編輯:這是我第一次嘗試重構..這是「Scala方式」嗎?
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
}
}
?
基本上,不知道類型,幾乎不可能診斷失敗。編譯器診斷可能會有所幫助,但您也沒有包括它們。也許有人熟悉協議緩衝區可能會弄清楚。 – 2013-02-15 03:14:48
我的問題不在於協議緩衝區。我的問題只是在搞清楚如何以Scala-ish的方式從我的dispatchMap對象中獲取有用的信息。我有所有protobuf的東西了。 – 2013-02-15 03:49:59
當然,如果沒有大量源自協議緩衝區的細節,就無法解釋或分析您的代碼。另外...什麼是「重複」? – 2013-02-15 04:38:46