我正在使用提取器来简化解析,在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 _ => {
}
}
答案 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