2014-04-03 80 views
0

假定以下的數據結構。提高模式匹配代碼

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) 

我現在寫的,有很多模式匹配的功能:

返回型getConditionFormula => 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等。一個看上去不錯的方式,但它似乎很緊湊,換內涵。我也注意到,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)如果formula是一個選言等... 有沒有辦法做到這一點相結合的所有情況?

+0

對於2),I可如果代碼真的是完全相同的,那麼你會不會使用父類? 'case BinaryConnenective(g0,g1)'? –

+0

是的,我可以匹配'BinaryConnnective'。但如果我在'BinaryConnnective'上的'公式'和'BinaryConnenective'上的'g'匹配,我怎樣才能確保它們都是'Conjunction'或者都是'Disjunction'等。 – Kigyo

回答

2

Option應該提供很多有用的功能,以簡化你的代碼。

例如,當你寫類似:

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

你可以只調用mapo.map(transform)

我也邀請您來看看filter功能的情況下,包括一個條件。

編輯:偉大的建議通過@ OM-NOM-NOM:對於也可用於推導(它們實際上是糖依託mapflatMapfilter等):

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

也有理解 –

+0

for-comprehensions是一個很好的建議。到目前爲止,我從來沒有在'Option'上使用它們。新代碼在編輯1中。對於我的第二個問題,你有什麼想法嗎? – Kigyo