Question

J’ai essayé d’expliquer la différence entre des instructions de commutateur et une correspondance de motif (F #) à quelques personnes, mais je n’ai pas vraiment été en mesure de bien l'expliquer. La plupart du temps, ils me regardaient et disaient "Alors, pourquoi ne pas simplement utiliser if..then..else".

Comment leur expliqueriez-vous?

EDIT! Merci à tous pour ces bonnes réponses, j'aimerais vraiment pouvoir marquer plusieurs bonnes réponses.

Était-ce utile?

La solution

Ayant déjà fait partie de "ces personnes", je ne sais pas s'il existe un moyen succinct de résumer en quoi la recherche de motifs est une si belle saveur. C'est expérientiel.

À l'époque où je venais de jeter un coup d'œil sur la recherche de correspondance des motifs et que je pensais que c'était une déclaration de commutateur glorifiée, je pense que je n'avais aucune expérience en programmation avec des types de données algébriques (n-uplets et syndicats discriminés) et que je ne voyais pas vraiment ce motif. la mise en correspondance était à la fois une construction de contrôle et une construction de liaison. Maintenant que je programme avec F #, je l’ai enfin "compris". La fraîcheur de la correspondance de motif est due à la confluence de fonctionnalités trouvées dans les langages de programmation fonctionnels, ce qui en fait un élément non négligeable que tout observateur extérieur apprécierait.

J'ai essayé de résumer un aspect de la raison pour laquelle la correspondance de modèle est utile dans la deuxième d'une série de blogs en deux parties sur le langage et la conception d'API; Découvrez la première partie et deuxième partie .

Autres conseils

Les modèles vous donnent un petit langage pour décrire la structure des valeurs que vous souhaitez faire correspondre. La structure peut être arbitrairement profonde et vous pouvez lier des variables à des parties de la valeur structurée.

Cela vous permet d’écrire des choses extrêmement succinctes. Vous pouvez illustrer cela avec un petit exemple, tel qu'une fonction dérivée pour un type simple d'expressions mathématiques:

type expr =
    | Int of int
    | Var of string
    | Add of expr * expr
    | Mul of expr * expr;;

let rec d(f, x) =
    match f with
    | Var y when x=y -> Int 1
    | Int _ | Var _ -> Int 0
    | Add(f, g) -> Add(d(f, x), d(g, x))
    | Mul(f, g) -> Add(Mul(f, d(g, x)), Mul(g, d(f, x)));;

De plus, étant donné que la recherche de modèle est une construction statique pour les types statiques, le compilateur peut (i) vérifier que vous avez couvert tous les cas (ii) détecter les branches redondantes qui ne peuvent jamais correspondre à une valeur (iii) fournir une implémentation très efficace (avec sauts, etc.).

Extrait de cet article de blog :

La correspondance de modèle présente plusieurs avantages par rapport aux instructions de commutateur et à l'envoi de méthode:

  • Les correspondances de modèle peuvent agir sur les ints, flotteurs, cordes et autres types comme ainsi que des objets.
  • Les correspondances de modèle peuvent agir sur plusieurs différentes valeurs simultanément: correspondance de modèle parallèle. Méthode l'envoi et la commutation sont limités à un seul valeur, par exemple "ceci".
  • Les motifs peuvent être imbriqués, permettant envoi sur des arbres d'arbitraire profondeur. L'envoi et le changement de méthode sont limités au cas non imbriqué.
  • Les motifs-or permettent aux sous-modèles d'être partagé. La méthode d'envoi ne permet que partage quand les méthodes sont de classes qui arrivent à partager une base classe. Sinon, vous devez manuellement factoriser les points communs dans un fonction séparée (en lui donnant une nom) puis insérer manuellement les appels de tous les endroits appropriés à votre fonction inutile.
  • La correspondance de modèle fournit la redondance vérification des erreurs détectées.
  • Motif imbriqué et / ou parallèle les matchs sont optimisés pour vous par le Compilateur F #. L'équivalent OO doit être écrit à la main et constamment réoptimisé à la main pendant développement, qui est prohibitif fastidieux et sujet aux erreurs, donc code OO de qualité de production a tendance à être extrêmement lent en comparaison.
  • Les modèles actifs vous permettent d’injecter sémantique d'expédition personnalisée.

De mémoire:

  1. Le compilateur peut dire si vous n'avez pas couvert toutes les possibilités de vos correspondances
  2. Vous pouvez utiliser une correspondance en tant qu'affectation
  3. Si vous avez un syndicat discriminé, chaque correspondance peut avoir un "type" différent

Le commutateur correspond aux deux roues avant.

La correspondance de modèle correspond à la voiture entière.

Les tuples ont ", " et les variantes ont des arguments Ctor .. ce sont des constructeurs, ils créent des choses.

Les modèles sont des destructeurs, ils les déchirent.

Ce sont deux concepts.

En termes plus précis: la notion de tuple ou de variante ne peut être décrite par son constructeur: le destructeur est requis ou la valeur que vous avez créée est inutile. Ce sont ces deux descriptions qui définissent une valeur.

En général, nous considérons les constructeurs comme des données et les destructeurs comme des flux de contrôle. Les destructeurs de variantes sont des branches alternatives (une parmi beaucoup), les destructeurs de tuple sont des threads parallèles (tous nombreux).

Le parallélisme est évident dans des opérations comme

(f * g) . (h * k) = (f . h * g . k) 

Si vous pensez au contrôle circulant dans une fonction, les n-uplets permettent de fractionner un calcul en threads de contrôle parallèles.

Dans cette optique, les expressions sont des moyens de composer des n-uplets et des variantes pour créer des structures de données compliquées (pensez à un AST).

Et les correspondances de motifs sont des façons de composer les destructeurs (encore une fois, pensez à un AST).

Les correspondances de modèles dans OCaml, en plus d’être plus expressives, comme mentionné de plusieurs manières décrites ci-dessus, donnent également des garanties statiques très importantes. Le compilateur vous prouvera que l'analyse de cas incarnée par votre déclaration de correspondance de modèle est la suivante:

  • exhaustif (aucun cas ne manque)
  • non redondant (aucun cas ne peut jamais être touché car il a été anticipé par un cas précédent)
  • son (aucun motif impossible compte tenu du type de données en question)

C'est vraiment un gros problème. C'est utile lorsque vous écrivez le programme pour la première fois, et extrêmement utile lorsque votre programme évolue. Utilisées correctement, les instructions de correspondance facilitent la modification fiable des types dans votre code, car le système de types vous dirige vers les instructions de correspondance brisées, qui sont un indicateur correct de l'endroit où vous avez du code à corriger.

Les instructions

If-Else (ou switch) concernent le choix de différentes manières de traiter une valeur (entrée) en fonction de propriétés de la valeur actuelle.

La correspondance de modèle consiste à définir comment traiter une valeur en fonction de sa structure (notez également que les correspondances de modèle de casse ont un sens).

Ainsi, l’appariement de formes consiste davantage à déconstruire des valeurs que à faire des choix, ce qui en fait un mécanisme très pratique pour définir des fonctions (récursives) sur des structures inductives (types d’union récursive), ce qui explique leur utilisation si abondante dans des langages tels que Ocaml, etc. .

PS: Peut-être connaissez-vous les correspondances de motif et les autres "modèles"? de leur utilisation ad hoc en maths;

"si x a la propriété A, alors y sinon z" (Si-Autre)

"un terme dans p1..pn où .... est la décomposition première de x .." (correspondance de modèle (cas unique))

Peut-être pourriez-vous faire une analogie avec les chaînes et les expressions régulières? Vous décrivez ce que vous recherchez et laissez le compilateur déterminer comment lui-même. Cela rend votre code beaucoup plus simple et clair.

En passant: je trouve que la chose la plus utile à propos du filtrage par motif est qu’il encourage les bonnes habitudes. Je traite avec les premiers premiers cas, et il est facile de vérifier que j'ai bien traité chaque cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top