Programmation fonctionnelle du point de vue d'EcmaScript. Fonctions pures, lambdas, immunité

Bonjour, Habr!

Aujourd'hui, nous allons commencer à parler d'un sujet très important - la programmation fonctionnelle. L'importance de la PF dans le développement Web moderne est difficile à surestimer. L'architecture de tout projet moderne à grande échelle comprend des bibliothèques de fonctions définies par l'utilisateur, et il y aura des questions obligatoires sur FI dans l'entretien à n'importe quel niveau.

Introduction à la programmation fonctionnelle


La programmation fonctionnelle (FP) est un moyen d'organiser le code en écrivant un ensemble de fonctions.

EcmaScript, étant un langage de programmation multi-paradigmes, implémente, entre autres, un paradigme fonctionnel. Cela signifie que les fonctions dans ES sont des données et peuvent être transmises à des fonctions, renvoyées par des fonctions et peuvent accepter des fonctions elles-mêmes. C'est-à-dire les fonctions dans ES sont des fonctions de première classe .

Les définitions suivantes en découlent:

Argument fonctionnel (funarg) - un argument dont la valeur est une fonction.

Une fonction d'ordre supérieur (FWP, fonctions d'ordre supérieur, hof) est une fonction qui accepte des fonctions comme arguments.

Fonctions avec une valeur fonctionnelle (Function value functions) - une fonction qui renvoie une fonction.

Tous ces types de fonctions sont conditionnellement combinés en fonctions de la première classe et, comme il résulte de la définition ci-dessus, dans ES toutes les fonctions sont des objets de la première classe.

Fonctions pures - l'idéal de la programmation fonctionnelle


Fonctions pures (PF) - renvoient toujours un résultat prédit.
Propriétés PF:

  • Le résultat de l'exécution de PF ne dépend que des arguments passés et de l'algorithme qui implémente PF
  • N'utilisez pas de valeurs globales
  • Ne modifiez pas les valeurs extérieures ou les arguments passés
  • N'écrivez pas de données dans des fichiers, des bases de données ou ailleurs

Un exemple de fonction pure:

const add = (x,y) => x+y; 

Un bon exemple d'impureté fonctionnelle est:

 var first; var second; function testFn() { var a = 10; first = function() { return ++a; } second = function() { return --a; } a = 2; first();//3 } testFn(); first();//4 second();//3 

Imaginez combien il est compliqué d'écrire des tests pour cet exemple et combien cela simplifie pour les fonctions pures!

Les fonctions impures sont caractérisées par un état externe variant dans le temps qui complique la maintenance, la compréhension et les tests de code.

Au contraire, les fonctions pures sont toujours lisibles, testables, simplifient la parallélisation des calculs et sont faciles à réutiliser.

Je pense que vous avez remarqué que dans les exemples sur les fonctions pures, je suis passé à la syntaxe ES6. Cela a été fait délibérément. Cette syntaxe de fonction est appelée "fonctions fléchées", mais en fait c'est une implémentation de l'abstraction mathématique, inventée il y a longtemps. À ce sujet plus loin.

Lambda - fonctions


C'est ce que l'on appelle cette forme d'écriture en flèche en mathématiques et dans d'autres langages de programmation. La programmation fonctionnelle est très étroitement liée au tapis. analyse, alors ne soyez pas surpris.

Le terme Lambda calcul a été introduit dans les années 1930 par Alonzo Church. En substance, le lambda calcul n'est rien de plus qu'une forme formelle de description d'une équation mathématique. Plus de détails ici .

En ES, une fonction lambda implémente très souvent une fermeture:

 const add = x => y => x + y; 

Court et concis. La fonction add est un lambda qui prend un argument x, le stocke dans une fermeture et retourne une fonction.

Comparez avec ce code:

 funtion add(x) { return function (y) { return x + y; } } 

De toute évidence, la première option semble meilleure.

Immunité


Immuable (immuable, immunité) est un objet dont l'état ne peut pas être changé après la création. Le résultat de toute modification d'un tel objet sera toujours un nouvel objet, tandis que l'ancien objet ne changera pas.

L'immuabilité est le graal d'or de la programmation fonctionnelle.

Prenons un exemple:

 const impureAddProp = (key, value, object) => { object[key] = value;//   }; const User= { name: 'Alex' }; impureAddProp ('isAdmin', true, User); 

Comme vous pouvez le voir, dans cet exemple, nous avons muté l'objet User en lui ajoutant une propriété. Maintenant, l'objet User est une sorte «d'état partagé» pour la fonction impureAddProp et d'autres fonctions qui le muteront. Cette approche est plus difficile à tester car Lors du changement d'une fonction interagissant avec un état partagé, il faut toujours garder à l'esprit les erreurs possibles dans d'autres fonctions.

Du point de vue de la programmation fonctionnelle, il serait correct:

 const pureAddProp = (key, value, object) => ({ ...object, [key]: value }); const User= { name: 'Alex' }; const Admin= pureAddProp ('isAdmin', true, User); 

Ainsi, l'objet utilisateur restera inchangé. Nous modifions une copie des données, ce qui est toujours sûr.

Conclusion


Aujourd'hui, nous avons examiné plusieurs concepts théoriques importants. Nous nous sommes familiarisés avec les fonctions pures, la forme lambda des fonctions d'enregistrement et le concept d'immuabilité en fp. Cependant, cet article est une sorte d'introduction. Les principales idées, techniques et «parties dures» de la programmation fonctionnelle figureront dans les articles suivants.

La programmation fonctionnelle est implémentée par de nombreuses bibliothèques. C'est rambda, lodash et bien d'autres. Dans un vrai projet, vous les utiliserez bien sûr. Sous le capot de toutes les bibliothèques, il y aura toujours le même javascript natif, donc dans les articles suivants, nous analyserons le FP, implémentant tous ses concepts sur JS natif.

Postscript


Commençant à écrire des articles, j'avais en tête le plan suivant:

  • rédiger des traductions d'articles intéressants en anglais
  • mettre en évidence plusieurs domaines pertinents dans JS (concepts clés, POO en termes de spécifications EcmaScript, modèles, programmation fonctionnelle).

À ce jour, des articles de fond dans trois domaines ont déjà été rédigés:

  1. ceci et ScopeChain en EcmaScript - ici, j'ai décrit des concepts clés de la spécification comme le contexte d'exécution, le mot-clé this et la propriété de contexte ScopeChain (chaîne de portée). Dans le cadre de cette direction, mon article sur l'environnement lexical et la fermeture a été publié littéralement aujourd'hui.
  2. Un regard d'EcmaScript sur la théorie générale de la POO - la différence entre le typage de classe statique et l'organisation de prototype dynamique a été décrite ici, le modèle de délégation et le typage de canard sont démontés
  3. Motifs élégants en JavaScript moderne (série de compilation Bill Sourour sur le cycle) - voici deux modèles qui peuvent être utiles dans certaines situations. Mon approche en termes de motifs est assez simple: il vaut mieux connaître autant de motifs que possible, car tôt ou tard sont utiles

Et maintenant, c'est au tour de la programmation fonctionnelle. À l'avenir, j'écrirai des articles dans le prolongement de chacun de ces domaines. Par exemple, l'article suivant portera sur les concepts clés de la POO: encapsulation, abstraction, impuretés (et coups), interfaces, etc. ... Je prévois également de parler de la façon dont la POO dans ES est implémentée sous le capot, c'est-à-dire sur les propriétés de [[Prototype]], [[Class]] et bien plus encore. Expliquez comment la v8 crée des entités et des instances de classes, de fonctions.

Beaucoup de questions se posent dans les commentaires, je voudrais donc expliquer les objectifs que je me suis fixés pour mes articles. Je n'écris pas de didacticiels ou n'examine pas la documentation. À mon avis, cela n'a aucun sens. Je ne vous conseille pas avec certains instruments ou motifs, leur choix est entièrement à vous.

Dans les articles, soit je passe en revue les concepts, je dis comment ils sont disposés sous le capot (à mon avis, cela améliore la compréhension de ce que nous écrivons et pourquoi nous écrivons de cette façon), soit je parle de certaines choses qui élargissent mes horizons. À mon avis, c'est très important. Jetez un oeil à des entreprises telles que Yandex ou Edadil, elles parlent constamment d'une sorte d'idées originales. Soit ce sont des bitmaps dans react, alors l'application vue est presque complètement sur les classes es6. La plupart des développeurs Web n'auraient jamais pensé à une telle chose. Cela nécessite une large perspective.

J'ai moi-même étudié et étudié le web de cette manière, c'est-à-dire après avoir lu un tutoriel ou un dock, j'essaie de comprendre comment l'outil décrit fonctionne sous le capot, de comprendre sa mécanique interne.

Jusqu'à de futurs articles, amis!

Source: https://habr.com/ru/post/fr474702/


All Articles