惯用Scala - 对元组值执行函数

时间:2013-02-15 01:54:31

标签: scala collections map tuples

民间,   我已经定义了以下地图和结构类型:

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”。

所以,这是我今天创建的消息,一个actor,并将消息发送给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和基于tuple._1的合并protobuf对象给出一个Akka actor的实例。

有人可以提出一种方法来对这些代码进行操作,减少行数并使其更具功能性吗? e.g。

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

1 个答案:

答案 0 :(得分:3)

您的代码可能是这样写的:

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

这可能是不对的。我没有尝试创建工作代码就这样做了,因为你的样本不是自包含的。此外,theBytes无法定义。

但我很确定你可以使用for comprehension来澄清和简化它。