【问题标题】:Scala syntax pattern matching on inner patternScala 语法模式匹配内部模式
【发布时间】:2018-03-30 00:51:16
【问题描述】:

我需要通过内部对象分解案例类,并且案例变得非常长。假设我只针对按类型分解的“上下文”内部对象的第一个参数的情况,是否有更好的方法来编写?


编辑:更改示例以反映讨论

    // context should be any opaque type that you want returned to you in your result message
  case class PopulateFeedVersionMessage(inoutContext: Any, sectionId : Int, feedId : Int, newVersion : String, oldVersion : String)


  trait PopulateDBReturnableMessage {
    val inputMessage : PopulateFeedVersionMessage
  }

  case class PopulateFeedFileNotExistsError(inputMessage : PopulateFeedVersionMessage, errorMessage : String) extends PopulateDBReturnableMessage
  case class PopulateFeedUploadError(inputMessage : PopulateFeedVersionMessage, errorMessage : String) extends PopulateDBReturnableMessage
  case class PopulateFeedRuntimeError(inputMessage : PopulateFeedVersionMessage, errorMessage : String) extends PopulateDBReturnableMessage

  case class PopulateDBResult(inputMessage: PopulateFeedVersionMessage, localNewDBPath : String, localOldDBPath : String, feedType : DatafeedType) extends PopulateDBReturnableMessage

假设在父演员中我这样做:

childActor ! PopulateFeedVersionMessage(inoutContext = interestingContextObjectForThisParticularMessage,sectionId = 1, feedId = 2, newVersion = "Some new version", oldVersion = "some old version")

在子actor中,我处理消息并决定使用PopulateDBReturnableMessage 类型(可以是resulterror 类型)进行响应

 // child
override def receive = {

    case message : PopulateFeedVersionMessage => sender ! handle(message)
  }

def handle(message : PopulateFeedVersionMessage) = {
...
// lets say we had an upload error because the disk is full or 401 or server down or what ever we can supply in the error message
  PopulateFeedUploadError(inputMessage = message, errorMessage : "The disk is full")
} 

现在回到父演员:

def receive = {
  case MessageType1 => {
    ... deciding what to do...
    ... decided to spawn a child actor with a context of interest...
    childActor ! PopulateFeedVersionMessage(inoutContext = interestingContextObjectForThisParticularMessage,sectionId = 1, feedId = 2, newVersion = "Some new version", oldVersion = "some old version")
  }
  // async handling the return message of the child with the context
  case m : PopulateDBReturnableMessage => m match {
      case PopulateFeedFileNotExistsError(inputMessage: PopulateFeedVersionMessage, errorMessage: String) => {
        // need to decompose the inputMessage.context as a inInterestingContextObjectForThisParticularMessage type
      }
      case PopulateFeedUploadError(inputMessage: PopulateFeedVersionMessage, errorMessage: String) => {

      }
      case PopulateFeedRuntimeError(inputMessage: PopulateFeedVersionMessage, errorMessage: String) => {
        // need to decompose the inputMessage.context as a inInterestingContextObjectForThisParticularMessage type
      }
      case PopulateDBResult(inputMessage: PopulateFeedVersionMessage, localNewDBPath: String, localOldDBPath: String, feedType: DatafeedType.DatafeedType) => {
        // need to decompose the inputMessage.context as a inInterestingContextObjectForThisParticularMessage type
      }
      case _ =>
    }
}

【问题讨论】:

  • 如果可能的话,我会质疑设计决策。为什么需要Any 的上下文?看起来像一个漏洞。
  • 因为它作为无法输入的akka​​消息的inout参数传递
  • 基本上,actor的输入消息包含一个参数,该参数可以作为不透明状态传回其发送者,以识别它运行的上下文的某些属性(例如可以是时间/日期/计数器/或与其运行相关的其他状态)
  • 并且输入输出状态的类型可能会根据可能出现的某些条件而改变(即,在某些情况下,传递一个日期可能很有趣,但在其他情况下,传递一个哈希值可能会很有趣可以识别状态的某种“事物”)
  • 我明白了。 foo 是否关心这些类的特定(重复)属性,还是它们通常不同?

标签: scala syntax pattern-matching traits


【解决方案1】:

你可以实现一个自定义匹配器(例如下面的InoutContext)来将PopulateFeedVersionMessage分解成inoutContext

  object InoutContext {
    def unapply(obj: PopulateFeedVersionMessage): Option[Any] = 
      Some(obj.inoutContext)
  }

然后,您可以像这样进行模式匹配:

 case PopulateFeedFileNotExistsError(
        InoutContext(strCtx: String), 
        errorMessage
      ) => {
   ...
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 2021-12-17
    • 1970-01-01
    • 2017-05-22
    • 2014-09-30
    相关资源
    最近更新 更多