改进模式匹配代码

时间:2014-04-03 14:01:25

标签: scala pattern-matching

假设以下数据结构。

sealed abstract class Formula {...}

//... some other case classes

sealed abstract class BinaryConnective(f0: Formula, f1: Formula) extends Formula {
  def getf0 = f0
  def getf1 = f1
}

object BinaryConnective {
  def unapply(bc : BinaryConnective) = Some((bc.getf0, bc.getf1))
}

final case class Conjunction(f0: Formula, f1: Formula) extends BinaryConnective(f0,f1)
final case class Disjunction(f0: Formula, f1: Formula) extends BinaryConnective(f0,f1)
final case class Implication(f0: Formula, f1: Formula) extends BinaryConnective(f0,f1)
final case class Equivalence(f0: Formula, f1: Formula) extends BinaryConnective(f0,f1)

我现在写了一个有很多模式匹配的函数:

getCondition的返回类型为Formula => Option[HashMap[Variable, Formula]]

formula match {
//.. irrelevant cases not shown
case Conjunction(f0, f1) => (g : Formula) => {
    g match {
      case conj @ Conjunction(g0, g1) => {
        getCondition(f0)(conj.f0) match {
          case Some(map0) => {
            getCondition(f1)(conj.f1) match {
             case Some(map1) if map0.forall{case (key, value) => map1.get(key).map(_ == value).getOrElse(true)} => {
               Some(map0 ++ map1)
             }
             case _ => None
            }
          }
          case None => None
        }
      }
      case _ => None
    }
  }
}

现在回答我的问题。

1)有没有更好的方式来表达这段代码?很多比赛正在进行中。

编辑1:我想不出一种使用mapfilter等内容的漂亮方式,但是对于for-comprehension看起来非常紧凑。我也注意到conj @根本没有必要,这也使它更简单。

case Conjunction(f0, f1) => (g: Formula) => g match {
  case Conjunction(g0, g1) => for {
      map0 <- getCondition(f0)(g0)
      map1 <- getCondition(f1)(g1)
      if map0.forall {case (key, value) => map1.get(key).map(_ ==  value).getOrElse(true)}
    } yield map0 ++ map1
  case _ => None
}

2)这是Conjunction的匹配。我必须重复DisjunctionImplicationEquivalenceg必须与formula属于同一类。唯一可以改变的是case conj @ Conjunction(g0, g1)。如果case disj @ Disjunction(g0, g1)是Disjunction等,我必须将其调整为formula ... 有没有办法在所有情况下合并?

1 个答案:

答案 0 :(得分:2)

Option应该提供许多有用的功能来简化代码。

例如,当您写下以下内容时:

o match {
  case Some(e) => Some(transform(e))
  case _ => None
}

您可以致电mapo.map(transform)

我还邀请您查看包含条件的案例的filter函数。

编辑:@ om-nom-nom的好建议:也可以使用理解(实际上它们依赖于mapflatMapfilter等等:)< / p>

for{
  e <- o
} yield transform(e)