2010-08-13 78 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