4 votes

Déclaration "if" / "match" imbriquée en Scala : meilleure approche?

Je dispose d'une série de fonctions de validation qui renvoient un Option[Problème], le cas échéant, ou None s'il n'y a aucun problème de validation trouvé. J'aimerais écrire une fonction simple qui appelle chaque fonction de validation, s'arrête et renvoie le premier résultat non None.

Évidemment, je peux écrire cette méthode de manière "à la Java", mais j'aimerais savoir s'il existe une meilleure approche.

ÉDITER

Voici la solution Java originale :

validate01(arg);
validate02(arg);
validate03(arg);
...

Chaque méthode lance une exception en cas de problème. Je préfère éviter les exceptions lorsque j'écris en Scala.

6voto

Kim Stebel Points 22873

Par exemple, supposons que nous voulons valider une String. Notre fonction de validation prend une String et une liste de validateurs, qui sont des fonctions de String à Option[Problème]. Nous pouvons l'implémenter de manière fonctionnelle comme ceci :

def premierProbleme(validateurs: List[String => Option[Problème]], s:String) =
  validateurs.view.flatMap(_(s)).headOption

Cela crée une nouvelle liste en appliquant chaque fonction de validation à la chaîne et en conservant le résultat uniquement s'il s'agit d'un Some. Nous prenons ensuite le premier élément de cette liste. En raison de l'appel à view, la liste sera calculée uniquement au besoin. Ainsi, dès que le premier Problème est trouvé, aucun autre validateur ne sera appelé.

6voto

om-nom-nom Points 33691

Si vous avez un nombre fini et connu au moment de la compilation de validations, vous pouvez utiliser .orElse sur Options:

def foo(x: Int): Option[Problem] = ...
def bar(x: Int): Option[Problem] = ...
...
def baz(x: Int): Option[Problem] = ...

foo(1) orElse bar(2) orElse .. baz(n)

1voto

Rex Kerr Points 94401

Peut-être que vous voulez - en supposant que les fonctions de validation ne prennent pas d'arguments

def firstProblem(fs: (() => Option[Problem])*) = {
  fs.iterator.map(f => f()).find(_.isDefined).flatten
}

Vous obtiendrez un Option[Problem] existant s'il y en a un, ou None s'ils réussissent tous. Si vous devez passer des arguments aux fonctions, alors vous devez expliquer quels sont ces arguments. Par exemple, vous pourriez

def firstProblem[A](a: A)(fs: (A => Option[Problem])*) = /* TODO */

si vous pouvez passer le même argument à tous. Vous l'utiliseriez comme ceci:

firstProblem(myData)(
  validatorA,
  validatorB,
  validatorC,
  validatorD
)

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