lenguaje - ¿Cómo se combinan los patrones de las grandes clases de casos de Scala?
scala introduccion (2)
Considere la siguiente clase de caso de Scala:
case class WideLoad(a: String, b: Int, c: Float, d: ActorRef, e: Date)
La coincidencia de patrones me permite extraer un campo y descartar otros, así:
someVal match {
case WideLoad(_, _, _, d, _) => d ! SomeMessage(...)
}
Lo que me gustaría hacer, y lo que es más relevante cuando una clase de caso tiene ~ 20 campos impares, es extraer solo algunos valores de una manera que no implique escribir WideLoad(_, _, _, _, _, some, _, _, _, thing, _, _, interesting)
.
Esperaba que los args nombrados pudieran ayudar aquí, aunque la siguiente sintaxis no funciona:
someVal match {
case WideLoad(d = dActor) => dActor ! SomeMessage(...)
// ^---------- does not compile
}
¿Hay alguna esperanza aquí, o estoy atascado tipeando muchos, muchos _, _, _, _
?
EDITAR : Entiendo que puedo hacer el case wl @ WideLoad(...whatever...) => wl.d
, pero aún me pregunto si hay incluso una sintaxis de terser que haga lo que necesito sin tener que introducir un valor adicional .
No sé si esto es apropiado, pero también puedes construir un objeto para que coincida con ese campo, o ese conjunto de campos (código no probado):
object WideLoadActorRef {
def unapply(wl: WideLoad): Option[ActorRef] = { Some(wl.d) }
}
someVal match {
case WideLoadActorRef(d) => d ! someMessage
}
o incluso
object WideLoadBnD {
def unapplySeq(wl: WideLoad): Option[(Int,ActorRef)] = { Some((wl.b,wl.d)) }
}
someVal match {
case WideLoadBnD(b, d) => d ! SomeMessage(b)
}
Siempre puedes recurrir a los guardias. No es realmente agradable, pero es mejor que la coincidencia de patrones normales para tus clases de casos de monstruos :-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
Dicho esto, creo que deberías reconsiderar tu diseño. Probablemente pueda agrupar lógicamente algunos parámetros utilizando clases de casos, tuplas, listas, conjuntos o mapas. Scala admite la coincidencia de patrones anidados:
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!