Movatterモバイル変換


[0]ホーム

URL:


Aller au contenu
Wikipédial'encyclopédie libre
Rechercher

Programmation fonctionnelle

Un article de Wikipédia, l'encyclopédie libre.

Laprogrammation fonctionnelle est unparadigme de programmation de typedéclaratif qui considère le calcul en tant qu'évaluation defonctions mathématiques.

Comme lechangement d'état et la mutation des données ne peuvent pas être représentés par des évaluations de fonctions sanseffet de bord[1], la programmation fonctionnelle les écarte : au contraire, elle met en avant l'application des fonctions, contrairement au modèle deprogrammation impérative, lequel met en avant les changements d'état[2].

Unlangage fonctionnel est donc unlangage de programmation dont la syntaxe et les caractéristiques encouragent la programmation fonctionnelle. Alors que l'origine de la programmation fonctionnelle peut être trouvée dans lelambda-calcul, le langage fonctionnel le plus ancien estLisp, créé en1958 parMcCarthy. Lisp a donné naissance à des variantes telles queScheme (1975) etCommon Lisp (1984)[3] qui, comme Lisp, ne sont pas ou peutypées. Des langages fonctionnels plus récents telsML (1973),Haskell (1987),OCaml,Erlang,Wolfram Language (1988)[4],[5], Clean etOz,CDuce,Scala (2003),F# ouPureScript (2013),Agda (en) sont fortement typés.

Machine à états et effets secondaires

[modifier |modifier le code]

Programmation fonctionnelle

[modifier |modifier le code]

La programmation fonctionnelle s'affranchit des effets secondaires (oueffets de bord) en interdisant toute opération d'affectation[1].

Le paradigme fonctionnel n'utilise pas demachine à états pour décrire un programme, mais un emboîtement de fonctions qui agissent comme des « boîtes noires » que l'on peut imbriquer les unes dans les autres. Chaque boîte possédant plusieursparamètres en entrée mais une seule sortie, elle ne peut sortir qu'une seule valeur possible pour chaquen-uplet de valeurs présentées en entrée.

Ainsi, les fonctions n'introduisent pas d'effets de bord. Un programme est donc uneapplication, au sens mathématique, qui ne donne qu'un seul résultat pour chaque ensemble de valeurs en entrée. Cette façon de penser, très différente de la démarche de la programmation impérative, est l'une des causes principales de la difficulté qu'ont les programmeurs formés aux langages impératifs pour aborder la programmation fonctionnelle.

Cependant, elle ne pose généralement pas de difficultés particulières aux débutants qui n'ont jamais été exposés à des langages impératifs[6].

Un avantage important des fonctions sans effet de bord est la facilité que l'on a à les tester unitairement. Par ailleurs, l'usage généralisé d'une gestion de mémoire automatique par l'intermédiaire d'unramasse-miettes simplifie la tâche du programmeur.

En pratique, pour des raisons d'efficacité, et du fait que certains algorithmes s'expriment aisément avec une machine à états, certains langages fonctionnels autorisent laprogrammation impérative en permettant de spécifier que certaines variables sont assignables (oumutables selon la dénomination habituelle), et doncla possibilité d'introduire localement des effets de bord[réf. nécessaire]. Ces langages sont regroupés sous le nom delangages fonctionnels impurs.

Les langages ditspurement fonctionnels n'autorisent pas la programmation impérative[1]. De fait, ils sont dénués d'effets de bord et protégés contre les problèmes que pose l'exécution concurrente. On peut voir par exemple ce qui a été fait dans le cadre du langageErlang.

La mise en œuvre des langages fonctionnels fait un usage sophistiqué de lapile car, afin de s'affranchir de la nécessité de stocker des données temporaires dans des tableaux, ils font largement appel à larécursivité (fait d'inclure l'appel d'une fonction dans sa propre définition). L'une des multiples techniques pour rendre la compilation de la récursivité plus efficace est une technique dénomméerécursion terminale (enanglais :tail-recursion), qui consiste à accumuler les résultats intermédiaires dans une case mémoire de la pile et à la passer en paramètre dans l'appel récursif. Ceci permet d'éviter d'empiler les appels récursifs dans la pile en les remplaçant par une simple succession de sauts. Le code généré par le compilateur est alors similaire à celui généré par une boucle en impératif. Certains langages commeScheme,Scala,OCaml et Anubis optimisent automatiquement les appels récursifs de cette manière.

Programmation impérative et effets de bord

[modifier |modifier le code]
Si ce bandeau n'est plus pertinent, retirez-le. Cliquez ici pour en savoir plus.
Si ce bandeau n'est plus pertinent, retirez-le. Cliquez ici pour en savoir plus.

Le contenu de cet article ou de cette section est peut-être sujet à caution etdoit absolument être sourcé().

Si vous connaissez le sujet dont traite l'article, merci de le reprendre à partir de sources pertinentes en utilisant notamment lesnotes de fin de page. Vous pouvez également laisser unmot d'explication en page de discussion.
Article détaillé :programmation impérative.

La programmation impérative s'appuie sur le modèle desmachines à états (voir aussimachine de Turing etArchitecture de von Neumann), avec unemémoire centrale et desinstructions qui modifient son état grâce à des affectations successives. Un tel programme est représenté par une machine à états (voirmachine à compteurs) qui représente les états successifs de la mémoire. Cela nécessite pour le programmeur d'avoir à tout instant un modèle exact de l'état de la mémoire que le programme modifie.

Afin de réduire lacomplexité de cette tâche, de nombreuses techniques réduisent le nombre de variables à gérer à un même instant, la plupart relèvent de laprogrammation structurée et de l'encapsulation de données :

  • les variables dites automatiques oulocales, sont restreintes au seul domaine (procédure, méthode, etc.) dans lequel elles sont utiles. Leurportée est alors strictement limitée à ce domaine.
  • l'encapsulation de données, notamment celle de laprogrammation orientée objet, restreint la manipulation des variables au seul domaine de laclasse à l'intérieur de laquelle elles sont définies (utilisation d'attributs privés)

Ces variables ont alors vocation à être désallouées par lecompilateur ouinterpréteur, immédiatement en sortie de procédure ou via unramasse-miettes.

Cependant, il arrive que laconception choisie par le programmeur l'amène à modifier dans certaines procédures, volontairement ou non, des variables ou des zones de mémoire « partagées », ne relevant pas structurellement de la procédure.Il se trouve qu'en programmation impérative, ces modifications «périphériques», désignées sous le terme générique d'effets secondaires (oueffets de bord),sontde facto plus la règle que l'exception[réf. nécessaire] et compliquent grandement la compréhension des programmes. Par conséquent, ils sont la source de nombreuses difficultés et debugs : en effet, si on oublie de mettre à jour certaines données partagées ou qu'au contraire on les modifie sans en mesurer tous les effets de bord, si l'ordre chronologique des affectations par les différents composants du logiciel est inadéquat, ou si une zone de mémoire est désallouée au mauvais moment, le programme se retrouve dans un état imprévu, incohérent voire instable et le programmeur est souvent incapable de détecter l'origine de l'erreur et s'il y réussit c'est au prix d'uneinstrumentation lourde des programmes.

Transparence référentielle

[modifier |modifier le code]

Les langages fonctionnels ont comme autre propriété latransparence référentielle. Ce terme recouvre le principe simple selon lequel le résultat du programme ne change pas si on remplace une expression par une expression devaleur égale. Ce principe est violé dans le cas de procédures à effets de bord puisqu'une telle procédure, ne dépendant pas uniquement de ses arguments d'entrée, ne se comporte pas forcément de façon identique à deux instants donnés du programme.

Prenons un exemple. EnC, sin désigne unevariable globale contenant un entier à incrémenter (donc une case mémoire visible par tout le programme), et siinc(k) est une fonction qui augmente la valeur den de la quantiték :

intn=2;intinc(intk){/* incrémentation par effet de bord */n=n+k;returnn;}f(inc(1)+inc(1));

Dans cet exemple, la fonctioninc(i) ne renvoie pas la même valeur lors des deux appels : l'un des arguments de la fonctionf vaudra2 + 1 = 3 et l'autre3 + 1 = 4. Il s'avère donc impossible de remplacerinc(i) + inc(i) par2 * inc(i) car la valeur deinc(i) diffère à chaque appel. Ce comportement est fondamentalement différent de celui d'une fonction mathématique. À l'échelle d'un programme important, cela signifie que le remplacement d'une fonction par une autre peut nécessiter des modifications à d'autres endroits du programme, et qu'il peut s'avérer nécessaire de retester l'intégralité du système, car on n'est pas assuré qu'un tel remplacement n'a pas modifié son comportement global. Au fur et à mesure que la complexité du système augmente, le coût d'un changement s'accroît aussi.À l'inverse, la propriété de transparence référentielle permet d'assurer que le remplacement d'une fonction par une autre équivalente ne risque pas de modifier le comportement global du programme. Autrement dit, elles sont mathématiquement égales. Cette propriété facilite la maintenance logicielle. Elle permet aussi d'appliquer de façon automatique des preuves de fonctionnement. Elle a enfin pour autre avantage de sensiblement réduire l'importance de l'ordre d'exécution, celui-ci étant assuré par l'ordre d'appel des fonctions ; un corollaire est que laparallélisation d'un programme fonctionnel peut être réalisée de façon automatique et que les optimisations que peuvent effectuer les compilateurs sont plus faciles à mettre en œuvre.

Des fonctions passées en paramètre

[modifier |modifier le code]

Les langages fonctionnels emploient destypes et desstructures de données de haut niveau comme les listes extensibles. Il est ainsi généralement possible de réaliser facilement des opérations comme laconcaténation de listes, ou l'application d'une fonction à une liste — le parcours de la liste se faisant de façon récursive —, en une seuleligne de code.

Un mécanisme puissant des langages fonctionnels est l'usage desfonctions d'ordre supérieur. Une fonction est dite d'ordre supérieur lorsqu'elle peut prendre des fonctions comme arguments (aussi appeléescallback) ou renvoyer une fonction comme résultat. On dit aussi que les fonctions sont des objets de première classe, ce qui signifie qu'elles sont manipulables aussi simplement que les types de base. Les programmes ou fonctions qui manipulent des fonctions correspondent, en mathématiques, auxfonctionnelles. Les opérations de dérivation et d'intégration en sont deux exemples simples. Les fonctions d'ordre supérieur ont été étudiées parAlonzo Church etStephen Kleene dans lesannées 1930, à partir du formalisme dulambda-calcul, qui a influencé la conception de plusieurs langages fonctionnels, notamment celle d'Haskell. Lathéorie des catégories cartésiennes fermées constitue une autre approche pour caractériser les fonctions, à l'aide de la notion deproblème universel. Le langage Anubis s'appuie sur cette théorie.

Impact du paradigme fonctionnel

[modifier |modifier le code]
Article détaillé :Algorithme récursif#Efficacité.

Au début des années 2000, la programmation fonctionnelle a commencé à sortir du milieu académique. Dans le milieu industriel, les langagesErlang (développé parEricsson pour des besoins de programmation concurrentielle et des impératifs de robustesse),Common Lisp,OCaml etScheme sont utilisés.Mais le développement des langages fonctionnels est limité par le déficit en outils et en bibliothèques de qualité commerciale, et surtout par le manque de programmeurs formés.[réf. nécessaire] Notons aussi le langageF# développé parMicrosoft Research est disponible souslicence de logiciel libre[7] en 2010[8].

Quoique les palmarès de la(en)compétition ICFPdémontrent le contraire[non neutre],les langages fonctionnels souffrent dans le premier quart duXXIe siècle d'une réputation de lenteuraujourd'hui complètement injustifiée[9][source insuffisante][non neutre] : certains compilateursScheme, comme les compilateurs Stalin ou Bigloo, les compilateurs pourCommon Lisp, les langages dans la lignée deML, tels queOCaml,Haskell ou encoreCDuce produisent des exécutables dont les performances moyennes sont comparables, en termes de temps d'exécution et d'espace, à ceux produits par les compilateursC ouC++.[source insuffisante]Un code sans effet de bord étantbeaucoup plus robuste et plus facile à maintenir, on le préférera à un programme dont la gestion de la mémoire et la prédiction du comportement seront difficiles à maîtriser, quitte à perdre un peu en efficacité[réf. nécessaire]. En outre, il faut aussi signaler les travaux de Chris Okasaki sur les structures de données purement fonctionnelles[10]qui rivalisent avec les structures mutables en efficacité et les outrepassent largement quand il s'agit de la robustesse[réf. nécessaire].

En dehors des universités et de secteurs industriels spécifiques,XSLT peut être un vecteur de popularisation du paradigme fonctionnel. Dédié au traitementXML, il permet à un programmeur de conserver ses langagesimpératifs ouobjets, tout en découvrant une autre logique de programmation.

De même les langagesScala et OCaml, qui se veulent des langages fonctionnels, permettent au programmeur qui en aurait besoin de rester dans une logique de programmation impérative.

Notes et références

[modifier |modifier le code]
  1. ab etcIl s'agit là d'un raccourci hâtif, mais le lecteur doit retenir que les langages fonctionnels n'ont pas a priori d'état. Cependant, grâce à la théorie desmonades, on peut y adjoindre des états, mais alors il faut le faire de façon explicite et consciente ; c’est l'affaire de programmeurs experts, et cette technique sort du cadre de cet article.
  2. (en)PaulHudak, « Conception, evolution, and application of functional programming languages »,ACM Computing Surveys,vol. 21,no 3,‎,p. 359-411(lire en ligne)
  3. auxquels il faut ajouterXSLT et Anubis.
  4. (en) « Functional Programming »
  5. « Functional vs. Procedural Programming Language », surweb.archive.org,(consulté le)
  6. (en) Manuel M. T. Chakravarty, Gabriele Keller, « The risks and benefits of teaching purely functional programming in first year. »,J. Funct. Program,vol. 14(1),‎,p. 113-123
  7. Plus précisément sous lalicence Apache
  8. (en)Announcing the F# Compiler + Library Source Code Drop, par Don Syme le 4 Nov 2010: « This source code is under the Apache 2.0 license and is published as part of the F# PowerPack codeplex project, which is now also under the Apache 2.0 license. The F# PowerPack now includes libraries, tools and the compiler/library source code drops. »
  9. (en)The “C is Efficient” Language Fallacy in ScienceBlogs.
  10. (en) Chris Okasaki, « Purely functional data structures »,Cambridge University Press New York, NY, USA,‎(ISBN 0-521-63124-6)

Voir aussi

[modifier |modifier le code]

Articles connexes

[modifier |modifier le code]

Bibliographie

[modifier |modifier le code]
  • Julien Dehos,La programmation fonctionnelle - Introduction et applications en Haskell à l'usage de l'étudiant et du développeur, Ellipses, 2019


v ·m
Impérative
Structurée
Déclarative
Métaprogrammation
Autres
Comparaison des langages de programmation multi-paradigmes
Ce document provient de « https://fr.wikipedia.org/w/index.php?title=Programmation_fonctionnelle&oldid=224497650 ».
Catégories :
Catégories cachées :

[8]ページ先頭

©2009-2025 Movatter.jp