60 votes

Correspondance de modèle avec des conjonctions (PatternA AND PatternB)

Scala est un langage à l'appui de disjonctions dans la correspondance de motif ("Pattern Alternatives'):

x match {
    case _: String | _: Int => 
    case _ =>
}

Cependant, j'ai souvent besoin de déclencher une action si le scrutinee satisfait PatternA et PatternB (conjonction.)

J'ai créé un modèle de combinateur '&&' qui ajoute cette fonctionnalité. Trois petites lignes qui vraiment me rappellent pourquoi j'aime la Scala!

// Splitter to apply two pattern matches on the same scrutinee.
object && {
  def unapply[A](a: A) = Some((a, a))
}

// Extractor object matching first character.
object StartsWith {
  def unapply(s: String) = s.headOption
}

// Extractor object matching last character.
object EndsWith {
  def unapply(s: String) = s.reverse.headOption
}

// Extractor object matching length.
object Length {
  def unapply(s: String) = Some(s.length)
}

"foo" match {
  case StartsWith('f') && EndsWith('f') => "f.*f"
  case StartsWith('f') && EndsWith(e) && Length(3) if "aeiou".contains(e) => "f..[aeiou]"
  case _ => "_"
}

Points de discussion

  1. Est-il un moyen de faire cela?
  2. Sont-il des problèmes avec cette approche?
  3. Existe-il d'autres utiles combinators qui pourraient être créés avec cette approche? (par exemple, Not)
  4. Si une telle combinator être ajouté à la bibliothèque standard?

Mise à JOUR J'ai juste demandé comment le compilateur interprète case A && B && C. Ce sont des opérateur infixe modèles (Section 8.1.9 de la Scala de Référence). Vous pouvez également exprimer cette normale extraire des motifs (8.1.7) &&(&&(A, B), C). Remarquez comment les expressions sont associés de gauche à droite, comme la normale opérateur infixe les appels de méthode comme Boolean#&& en val b = true && false && true.

13voto

Daniel C. Sobral Points 159554

J'aime vraiment ce truc. Je ne connais aucun moyen existant de le faire, et je ne prévois aucun problème avec cela - ce qui ne veut pas dire grand chose, cependant. Je ne vois aucun moyen de créer un Not .

Quant à l'ajouter à la bibliothèque standard ... peut-être. Mais je pense que c'est un peu difficile. D'autre part, que diriez-vous d'inclure les gens de Scalaz? Cela ressemble beaucoup plus à leur propre bailliage.

11voto

retronym Points 35066

Un problème possible avec ce est le ballonnement de la traduction que le modèle de correspondance génère. Voici la traduction de l'exemple de programme, généré avec scalac -print. Même -optimise ne parvient pas à simplifier l' if (true) "_" else throw new MatchError() expressions.

Grand modèle correspond déjà à générer plus de bytecode que ce qui est légal pour une méthode unique, et l'utilisation de ce combinateur peut amplifier le problème.

Si && a été intégré dans la langue, peut-être, la traduction pourrait être plus intelligent. Sinon, les petites améliorations -optimise pourrait aider.

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