7
votes

Pourquoi la programmation fonctionnelle est-elle bonne?

J'ai remarqué qu'il existe certains concepts de base que beaucoup de fanatiques de programmation fonctionnelle s'accrochent à:

  • Eviter l'état

  • Éviter les données mutables

  • minimiser les effets secondaires

  • etc ...

    Je ne me demandais pas simplement quelles autres choses rendent la programmation fonctionnelle, mais pourquoi ces idées de base sont bonnes? Pourquoi est-il bon d'éviter l'état, et le reste?


0 commentaires

4 Réponses :


13
votes

La réponse simple est que si vous n'avez pas d'état supplémentaire à vous inquiéter, votre code est plus simple de raisonner. Le code plus simple est plus facile à maintenir. Vous n'avez pas besoin de vous soucier des choses en dehors d'une pièce de code particulière (comme une fonction) pour la modifier. Cela a des ramifications vraiment utiles pour des choses comme des tests. Si votre code ne dépend pas d'un État, il devient beaucoup plus facile de créer des tests automatisés pour ce code, car vous n'avez pas à vous soucier de l'initialisation de certains Etat.

Le code apatride permet de créer également des programmes filetés, car vous n'avez pas besoin de vous inquiéter de deux threads d'exécution modifiant / lisant un morceau de données partagé en même temps. Vos threads peuvent exécuter un code indépendant, ce qui peut enregistrer des charges du temps de développement.

Essentiellement, éviter l'état crée des programmes plus simples. D'une certaine manière, il y a moins de "pièces mobiles" (c'est-à-dire des lignes de code de code peuvent interagir). Cela signifie donc généralement que le code est plus fiable et contient moins de défauts. Fondamentalement, plus le code est plus simple, moins peut aller mal. C'est l'essence de l'écriture du code sans état.

Il y a beaucoup d'autres raisons de créer un code apatride, "fonctionnel", mais ils bouchent tous à la simplicité pour moi.


2 commentaires

Devrait probablement mentionner la concurrence est plus facile à faire correctement?


+1. Bien dit, Oleksi.



5
votes

En plus de ce que @Oleksi a dit, il existe une autre chose importante: transparence référentielle et structures de données transactionnelles. Bien sûr, vous n'avez pas besoin d'un langage de programmation fonctionnel pour le faire, mais c'est un peu plus facile avec eux.

Les structures de données purement fonctionnelles sont garanties de rester les mêmes - Si une fonction renvoya un arbre, ce sera toujours le même arbre, et toutes les transformations supplémentaires en créeraient de nouvelles copies. Il est beaucoup plus facile de revenir en arrière à toute version précédente d'une structure de données de cette façon, ce qui est important pour de nombreux algorithmes essentiels.


0 commentaires

5
votes

Très généralement, des moyens de programmation fonctionnelle:

  • Encourager l'utilisation de fonctions (première classe)
  • décourageant l'utilisation de l'état (mutable)

    Pourquoi la mutation est-elle un problème? Pensez-y: la mutation concerne les structures de données que goto est de contrôler le flux. C'est-à-dire, cela vous permet de "sauter" arbitrairement à quelque chose de complètement différent de manière assez non structurée. Par conséquent, il est parfois utile, mais la plupart du temps plutôt préjudiciable à la lisibilité, à la qualification et à la composition.


1 commentaires

+1 pour comparer l'état mutable avec goto!



2
votes

Une caractéristique fonctionnelle typique est "Aucun sous-typing". Bien que cela semble un peu étrange d'appeler cela une fonctionnalité, c'est pour deux raisons (en quelque sorte liées):

  • Les relations de sous-typage mènent à un tas de problèmes non si évidents. Si vous ne vous limitez pas à une héritage célibataire ou de mixage, vous vous retrouvez avec le problème du diamant. Plus important encore, c'est que vous devez faire face à la variance (covariance, contrevenance, invariance), qui devient rapidement un cauchemar, en particulier pour les paramètres de type (A.K.A. Generics). Il y a plusieurs autres raisons et même dans les langues de l'OO, vous entendez des déclarations telles que "préférez la composition sur l'héritage".
  • D'autre part, si vous laissez simplement une sous-typing, vous pouvez raisonner beaucoup plus détaillé de votre système de type, ce qui conduit à la possibilité d'avoir (presque) une inférence de type complète, généralement mise en œuvre à l'aide d'extensions de l'inférence de type Hindley Milner.

    Bien sûr, vous manquerez parfois la sous-typing, mais des langues comme HASKELL ont trouvé une bonne réponse à ce problème: les classes de type, qui permettent de définir une sorte d'interface commune (ou «ensemble d'opérations communes») pour plusieurs Sinon, des types non liés. La différence pour les langues oo est que les classes de type peuvent être définies "après", sans toucher les définitions de type d'origine. Il s'avère que vous pouvez faire presque tout avec des classes de type que vous pouvez faire avec le sous-typing, mais de manière beaucoup plus flexible (et sans prévenir l'inférence de type). C'est pourquoi d'autres langues commencent à utiliser des mécanismes similaires (par exemple, des conversions implicites dans les méthodes Scala ou Extension en C # et Java 8)


0 commentaires