2010-08-13 11 views
36

Tenga en cuenta la siguiente clase de caso Scala:¿Cómo se combinan los patrones de las grandes clases de casos de Scala?

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

patrón coincidente 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 unos pocos valores de una manera que no implique escribir WideLoad(_, _, _, _, _, some, _, _, _, thing, _, _, interesting).

Yo esperaba que argumentos nombrados podrían ayudar aquí, aunque la sintaxis siguiente no funciona:

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

¿Hay alguna esperanza aquí, o estoy atascado escribiendo a cabo muchos, muchos _, _, _, _?

EDITAR: Entiendo que puedo hacer case wl @ WideLoad(...whatever...) => wl.d, sin embargo, todavía estoy preguntando si hay sintaxis incluso más concisa que hace lo que necesita sin tener que introducir un extra val.

+0

incluso con 4 o 5 campos, todos los guiones hacen que sea muy difícil de leer. Una sintaxis de parámetros nombrados mejoraría mucho la legibilidad, pero hasta donde sé, todavía no existe nada como esto. –

+0

Tenía la impresión de que las largas listas de parámetros son algo que se debe evitar en general. –

+0

Querías decir el caso WideLoad (d == dActor) –

Respuesta

34

No sé si este es el caso, pero también se puede construir un objeto sólo para que coincida con el 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) 
} 
+0

Me gusta mucho tu idea. Hace exactamente lo que necesito, con poca sintaxis adicional, intención definida explícitamente, seguridad tipográfica, etc. Es una gran solución de intervalo de detención hasta el momento en que refactoreé este código para tener clases de casos más pequeños. –

15

Siempre puede recurrir a las protecciones. No es muy agradable, pero mejor que la pauta normal coincidentes para que las clases de casos monstruo :-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 

que decía que yo creo que debería replantearse su diseño. Probablemente pueda agrupar lógicamente algunos parámetros utilizando clases de casos, tuplas, listas, conjuntos o mapas. Scala hace apoyo anidado coincidencia de patrones:

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

Sí, estoy refaccionando para alcanzar ese objetivo. Puede ser más fácil hacer esto que construir castillos de arena similares a los que propuse en mi pregunta. –

Cuestiones relacionadas