2015-05-26 32 views
2

有沒有辦法在Scala中以更優雅的方式編寫此代碼?Scala中的一行布爾模式匹配

基本上我有以下代數數據類型:

trait Exp 
case class Atom(i: Int) extends Exp 
case class Add(l: Exp, r: Exp) extends Exp 

和我要檢查,如果給定的變量內 的條件表達式的特定術語相匹配。例如,我可以寫

val x = Add(Atom(1), Atom(2)) 

if (x match { case Add(Atom(1), Atom(2)) => true; case _ => false }) { 
    println("match") 
}    

但是,它很醜且冗長。有沒有更優雅的選擇?

回答

4

您可以使用PartialFunction及其isDefinedAt方法:

type MatchExp = PartialFunction[Exp, Unit] // alias 

val isOnePlusTwo: MatchExp = { 
    case Add(Atom(1), Atom(2)) => 
} 

if (isOnePlusTwo.isDefinedAt(x)) println("match") 

一個match表達或者產生一個FunctionPartialFunction,取決於預期的類型。這裏的類型別名只是爲了方便。


另一種可能性,如果不通過模式匹配需要去構建,是單純依靠表達的平等:

if (x == Add(Atom(1), Atom(2))) println("match") 

這工作,因爲你使用case class ES具有正確的平等實現。

+0

「常」 的評論是不正確的;你必須有一個預期的類型Func或PF。此外,我的答案中的幫手方法,儘管它們永遠不會變得髖關節,但它一直保持低調,但看起來好多了。 –

+0

@ som-snytt你是對的,我刪除了錯誤的句子。 –

2

你可以把printlnmatch和擺脫if完全的:

x match { 
    case Add(Atom(1), Atom(2)) => println("match") 
    case _ => {} //do nothing 
} 
4

使用這些爲簡潔:

scala> import PartialFunction._ 
import PartialFunction._ 

scala> condOpt(x) { case Add(Atom(x), Atom(y)) => x + y } 
res2: Option[Int] = Some(3) 

scala> cond(x) { case Add(Atom(x), Atom(y)) => println("yep"); true } 
yep 
res3: Boolean = true 

scala> List(x, Atom(42)) flatMap (condOpt(_) { case Add(Atom(x), Atom(y)) => x + y }) 
res4: List[Int] = List(3)