如何模式匹配大型斯卡拉案例类?
考虑下面的Scala案例类:
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)
。
我希望命名的参数可以在这里帮助,虽然下面的语法不起作用:
someVal match { case WideLoad(d = dActor) => dActor ! SomeMessage(...) // ^---------- does not compile }
这里有没有希望,或者我打出了很多很多, _, _, _, _
?
编辑 :我明白,我可以做case wl @ WideLoad(...whatever...) => wl.d
,但我仍然想知道是否有甚至terser语法,做我所需要的,而不必引入额外的val
。
我不知道这是否合适,但你也可以build立一个对象,只是为了匹配该字段,或该字段集(未经testing的代码):
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) }
你总是可以回到守卫。 这不是很好,但比你的怪物案例类的正常模式匹配更好:-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
这就是说我认为你应该重新考虑你的devise。 也许你可以使用大小写类,元组,列表,集合或映射在逻辑上将一些参数分组在一起。 Scala支持嵌套模式匹配:
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!