Scala联合模式匹配允许可选术语

时间:2015-09-04 10:59:15

标签: scala pattern-matching

我正在使用提取器来简化解析,在Scala中编写一个小的解析例程。在我的研究过程中,我发现了一个非常有用的连接模式匹配(Pattern matching with conjunctions (PatternA AND PatternB))。使用它我已经能够表达如下的提取器(仅限概述)。

case object & {
    def unapply[T](t : T) = Some(t, t)
  }


case object ParamA {
    def unapply(jsonStr: String) : Option[String] = {
      // If param A found in json return a Some(...) else None
    ???
    }
  }
  case object ParamB {
    def unapply(jsonStr: String) : Option[String] = {
      // If param B found in json return a Some(...) else None
      ???
    }
  }
  case object ParamC {
    def unapply(jsonStr: String) : Option[String] = {
      // If param C found in json return a Some(...) else None
      ???
    }
  }

这些让我匹配下面的强制ParamA和ParamB模式。

val jsonStr = "..." // A Json string
    jsonStr match {
      case ParamA(a) & ParamB(b) => {
        // Got a and b. Now do something with it
      }
      case _ => {

      }
    }

但是,如果我想匹配强制ParamA和ParamB模式以及可选的ParamC模式,我将如何在一行中表达它?

val jsonStr = "..." // A Json string
    jsonStr match {
      case ParamA(a) & ParamB(b) & Optional(ParamC(c)) /* Is this possible? */ => {
        // Got a and b and an optional c. Now do something with it
      }
      case _ => {

      }
    }

1 个答案:

答案 0 :(得分:1)

您可以将unapply返回的值换行到另一个Option

case object OptionalParamC {
    def unapply(jsonStr: String) : Option[Option[String]] = {
      // If param C found in json return a Some(Some(...)) else Some(None)
    }
  }

这种情况总是匹配,但OptionalParamC(c)中的c是Some(x)None

更通用的方法是定义提取变压器

case object ? {

    type Extractor = {def unapply(t: String): Option[String]}

    case class Inner[T <: Extractor](extractor: T){
      def unapply(t: String) = Some(extractor.unapply(t))
    }

    def apply[T <: Extractor](extractor: T) = Inner(extractor)

  }

然后用它转换ParamC

val OptionalC = ?(ParamC)

最后像这样使用它:

ParamA(a) & ParamB(b) & OptionalC(c)

与c beeing Some(x)None