2010-08-13 115 views
36

考慮下面的斯卡拉案例類:如何模式匹配大型斯卡拉案例類?

case class WideLoad(a: String, b: Int, c: Float, d: ActorRef, e: Date) 

模式匹配允許我以提取一個場,並丟棄他人,就像這樣:

someVal match { 
    case WideLoad(_, _, _, d, _) => d ! SomeMessage(...) 
} 

我想什麼做的,更重要的是相關的時一個case類具有〜20個奇數字段,是以不涉及輸入WideLoad(_, _, _, _, _, some, _, _, _, thing, _, _, interesting)的方式僅提取幾個值。

我希望評爲ARGS可以幫助在這裏,雖然下面的語法不工作:

someVal match { 
    case WideLoad(d = dActor) => dActor ! SomeMessage(...) 
    //    ^---------- does not compile 
} 

是否有希望在這裏,還是我堅持打字了很多,很多_, _, _, _

編輯:我知道我可以做case wl @ WideLoad(...whatever...) => wl.d,但我一直在想,做什麼,我需要,而不必引入額外val是否甚至還有更簡潔的語法。

+0

,所有的下劃線讓它非常難以閱讀。一個命名參數語法可以提高可讀性,但據我所知,目前還不存在。 – 2010-08-13 06:14:11

+0

我的印象是,長參數列表通常是可以避免的。 – 2010-08-13 07:41:15

+0

你的意思是WideLoad(d == dActor) – 2010-08-14 03:01:44

回答

34

我不知道這是否是合適的,但你也可以建立一個對象只是爲了那場,或字段集(未經測試的代碼)相匹配:

object WideLoadActorRef { 
    def unapply(wl: WideLoad): Option[ActorRef] = { Some(wl.d) } 
} 

someVal match { 
    case WideLoadActorRef(d) => d ! someMessage 
} 

甚至

object WideLoadBnD { 
    def unapplySeq(wl: WideLoad): Option[(Int,ActorRef)] = { Some((wl.b,wl.d)) } 
} 

someVal match { 
    case WideLoadBnD(b, d) => d ! SomeMessage(b) 
} 
即使有4個或5場
+0

我很喜歡你的想法。它完全符合我的需求,只需要額外的語法,明確定義的意圖,類型安全等。這是一個很好的停止差距解決方案,直到我將這些代碼重構爲小型案例類爲止。 – 2010-08-13 12:06:43

15

你可以隨時迴避。這不是很好,但比你的怪物案例類的正常模式匹配更好:-P

case class Foo(a:Int, b:Int, c:String, d:java.util.Date) 

def f(foo:Foo) = foo match { 
    case fo:Foo if fo.c == "X" => println("found") 
    case _ => println("arrgh!") 
} 

f(Foo(1,2,"C",new java.util.Date())) //--> arrgh! 
f(Foo(1,2,"X",new java.util.Date())) //--> found 

這就是說我認爲你應該重新考慮你的設計。可能你可以使用大小寫類,元組,列表,集合或映射在邏輯上將一些參數分組在一起。斯卡拉確實支持嵌套模式匹配:

case class Bar(a: Int, b:String) 
case class Baz(c:java.util.Date, d:String) 
case class Foo(bar:Bar, baz:Baz) 

def f(foo:Foo) = foo match { 
    case Foo(Bar(1,_),Baz(_,"X")) => println("found") 
    case _ => println("arrgh!") 
} 

f(Foo(Bar(1,"c"),Baz(new java.util.Date, "X"))) //--> found 
f(Foo(Bar(1,"c"),Baz(new java.util.Date, "Y"))) //--> arrgh! 
+0

是的,我正在重構這個目標。做這件事比建造類似於我在我的問題中提出的沙堡更容易。 – 2010-08-13 12:05:08