En fait, ils sont fondamentalement très différents! Au moins en Haskell, en tout cas.
Les gardes sont à la fois plus simple et plus souple: Ils sont essentiellement juste une syntaxe spéciale, qui se traduit par une série de if/then expressions. Vous pouvez mettre arbitraire des expressions booléennes dans les gardes, mais ils ne font pas quelque chose que vous ne pouvais pas le faire avec une brosse if
.
Modèle correspond à faire plusieurs autres choses: Ils sont la seule façon de déconstruire les données, et ils se lient identifiants au sein de leur champ d'application. Dans le même sens que les gardes sont équivalentes if
expressions, le filtrage est équivalent à case
expressions. Déclarations (soit au plus haut niveau, ou à quelque chose comme un let
expression) sont aussi une forme de motif, à la "normale" définitions des matches avec le trivial, un identifiant unique.
Le motif correspond également tendance à être le moyen principal de trucs qui se passe réellement dans Haskell--la tentative de déconstruire des données dans un modèle est l'une des rares choses que les forces de l'évaluation.
Par ailleurs, vous pouvez effectivement faire un filtrage au niveau supérieur déclarations:
square = (^2)
(one:four:nine:_) = map square [1..]
C'est parfois utile pour un groupe de définitions connexes.
GHC également fournit la ViewPatterns extension qui combine à la fois; vous pouvez utiliser des fonctions arbitraires dans un contexte de liaison, puis correspondance de modèle sur le résultat. Ce n'est encore qu'sucre syntaxique pour les trucs habituels, bien sûr.
Comme pour la journée-à-jour de question de l'utiliser, voici quelques rough guides:
Certainement utiliser le pattern matching pour tout ce qui peut être associé directement à un ou deux constructeurs de profondeur, où vous n'avez pas vraiment sur le composé de données dans son ensemble, mais ne se soucient plus de la structure. L' @
syntaxe vous permet de lier l'ensemble de la structure à une variable tout en pattern matching sur elle, mais de faire trop de que, dans un modèle peut devenir moche et illisible rapidement.
Certainement utiliser gardes lorsque vous avez besoin de faire un choix basé sur des biens qui ne correspondent pas parfaitement à un modèle, par exemple en comparant les deux Int
valeurs pour voir qui est plus grand.
Si vous avez besoin de seulement un couple de morceaux de données à partir du plus profond à l'intérieur d'une grande structure, en particulier si vous avez besoin d'utiliser l'ensemble de la structure, les gardes et les fonctions d'accesseur sont généralement plus lisible que certains monstrueux modèle plein de @
et _
.
Si vous avez besoin de faire la même chose pour les valeurs représentées par des modèles différents, mais avec une pratique de prédicat à les classer, à l'aide d'un seul modèle générique avec un garde est habituellement plus lisible. Notez que si un ensemble de gardes est non-exhaustive, tout ce qui échoue tous les gardes de la liste déroulante pour le motif suivant (le cas échéant). Ainsi, vous pouvez combiner un modèle général avec certains filtres pour attraper des cas exceptionnels, puis faire un patron sur tout le reste pour obtenir plus de détails à vous soucier.
Certainement ne pas utiliser des protections pour les choses qui pourraient être trivialement vérifiée avec un motif. La vérification de vide listes est l'exemple classique, l'utilisation d'un motif pour cela.
En général, en cas de doute, il suffit de coller avec la correspondance de modèle par défaut, il est généralement plus agréable. Si un pattern commence à devenir vraiment laid ou compliquées, alors arrêtez de considérer de quelle autre façon vous pouvez l'écrire. Outre l'utilisation de gardes, d'autres options incluent l'extraction des sous-expressions dans des fonctions ou de la mettre case
expressions à l'intérieur du corps de la fonction, afin de pousser une partie de la correspondance de modèle vers le bas sur eux, ainsi que de la principale définition.