2013-02-15 26 views
0

夥計們, 我有以下的地圖和結構類型定義:慣用斯卡拉 - 元組上執行函數的值

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 
    } 
} 

+0

基本上,不知道類型,幾乎不可能診斷失敗。編譯器診斷可能會有所幫助,但您也沒有包括它們。也許有人熟悉協議緩衝區可能會弄清楚。 – 2013-02-15 03:14:48

+0

我的問題不在於協議緩衝區。我的問題只是在搞清楚如何以Scala-ish的方式從我的dispatchMap對象中獲取有用的信息。我有所有protobuf的東西了。 – 2013-02-15 03:49:59

+0

當然,如果沒有大量源自協議緩衝區的細節,就無法解釋或分析您的代碼。另外...什麼是「重複」? – 2013-02-15 04:38:46

回答

3

您的代碼可能會被寫成這樣:

val akkaResponseFuture = 
    for ((bytes, actorPath) <- dispatchMap.get(messageType); 
     theMessage   <- bytes.mergeFrom(theBytes); 
     targetActor  = SocketServer.system.actorFor(actorPath)) 
    yield 
    targetActor ! theMessage 

這很可能是不對的。我沒有嘗試創建工作代碼,因爲您的示例不是獨立的。另外,theBytes沒有定義。

但我敢肯定你可以使用理解來澄清和精簡它。

+0

@KevinHoffman:沒有冒犯,但你原來的問題很難閱讀,但在評論中的多行代碼是不可能的。你會用這個迴應來修改你的問題嗎? – 2013-02-15 03:05:19

+0

我花了過去5分鐘試圖弄清楚如何獲得代碼到評論中..我將編輯原始:) – 2013-02-15 03:06:41