44 votes

Comment faire correspondre les grandes classes de cas Scala?

Considérez les points suivants Scala cas de la classe:

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

La correspondance de modèle me permet d'en extraire un champ et jeter les autres, comme suit:

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

Ce que je voudrais faire, et quoi de plus pertinent qu'un cas de classe a ~20 odd champs, est d'extraire seulement quelques valeurs dans une voie qui n'implique pas de taper WideLoad(_, _, _, _, _, some, _, _, _, thing, _, _, interesting).

J'espérais que nommé args pourrait aider ici, bien que la syntaxe suivante ne fonctionne pas:

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

Est-il de l'espoir ici, ou suis-je coincé taper beaucoup, beaucoup d' _, _, _, _?

EDIT: je comprends que je peux faire, case wl @ WideLoad(...whatever...) => wl.d, pourtant je suis toujours demander si il n'y a même terser syntaxe qui fait ce dont j'ai besoin sans avoir à introduire une extra - val.

38voto

Magnus Points 918

Je ne sais pas si cela est approprié, mais vous pouvez également créer un objet juste pour correspondre à ce champ ou à cet ensemble de champs (code non testé):

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

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

ou même

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

someVal match {
  case WideLoadBnD(b, d) => d ! SomeMessage(b)
}
 

16voto

Landei Points 30509

Vous pouvez toujours vous rabattre sur les gardes. Ce n'est pas vraiment sympa, mais mieux que la correspondance de motifs normale pour vos classes de cas de monstres :-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
 

Cela dit, je pense que vous devriez repenser votre conception. Vous pouvez probablement regrouper logiquement certains paramètres en utilisant des classes de cas, des tuples, des listes, des ensembles ou des cartes. Scala prend en charge la correspondance de modèles imbriqués:

 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! 
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X