Les langages de pro­gram­ma­tion les plus courants per­met­tent gé­né­ra­le­ment d’utiliser des pa­ra­digmes de pro­gram­ma­tion dif­fé­rents. Il est ainsi possible d’établir de manière générale une dis­tinc­tion entre pro­gram­ma­tion dé­cla­ra­tive et pro­gram­ma­tion im­pé­ra­tive. Pour sim­pli­fier, ces pa­ra­digmes dé­fi­nis­sent l’approche de base adoptée par les logiciels de pro­gram­ma­tion. La pro­gram­ma­tion dite fonc­tion­nelle relève d’une approche dé­cla­ra­tive. Elle est utilisée en par­ti­cu­lier dans le dé­ve­lop­pe­ment des pro­grammes ou codes suivants :

  • ap­pli­ca­tions tech­niques et ma­thé­ma­tiques
  • in­tel­li­gence ar­ti­fi­cielle (IA)
  • com­pi­la­teurs et parseurs
  • al­go­rithmes

Dans quoi réside l’intérêt lié au paradigme fonc­tion­nel dans le cadre de ce type d’ap­pli­ca­tion in­for­ma­tique ? Et quelle est la dif­fé­rence avec des concepts comme la pro­gram­ma­tion orientée objet ?

Qu’est-ce que la pro­gram­ma­tion fonc­tion­nelle ?

Comme son nom l’indique, l’approche fonc­tion­nelle de la pro­gram­ma­tion se concentre sur la notion de fonctions. Dans un programme fonc­tion­nel, tous les éléments peuvent être compris comme des fonctions et le code peut être exécuté par des appels suc­ces­sifs de fonctions. À l’inverse, aucune valeur n’est assignée de façon in­dé­pen­dante. On peut se re­pré­sen­ter une fonction comme étant la variante spéciale d'un sous-programme donné. Elle est réu­ti­li­sable et, con­trai­re­ment à une procédure, renvoie di­rec­te­ment un résultat.

Bien sûr, dans de nombreux langages de pro­gram­ma­tion évolués, il existe des fonctions qui sont définies puis ap­pli­quées. Il ne s'agit donc pas de la par­ti­cu­la­rité prin­ci­pale de la pro­gram­ma­tion fonc­tion­nelle. Ce qui rend l'ap­proche fonc­tion­nelle si im­por­tante pour l'in­for­ma­tique et qui fait toute sa po­ly­va­lence, c'est le fait que les fonctions de ce paradigme de pro­gram­ma­tion peuvent prendre dif­fé­rentes « formes ». Par exemple, elles peuvent être associées entre elles comme des données. Elles peuvent également être utilisées en tant que pa­ra­mètres et résultats de fonctions. Ce trai­te­ment spécial des fonctions permet aux pro­gram­meurs de mettre en place et de traiter des tâches de calcul de grande envergure (en par­ti­cu­lier celles qui relèvent d’une nature sym­bo­lique).

Pourquoi la pro­gram­ma­tion fonc­tion­nelle est plus que jamais d’actualité

Bien que les racines de la pro­gram­ma­tion fonc­tion­nelle remontent aux années 1930 (dans le cadre de la recherche ma­thé­ma­tique fon­da­men­tale), l’approche fonc­tion­nelle jouit encore d’une grande po­pu­la­rité, surtout dans les domaines tech­niques et en ma­thé­ma­tiques. Il y a plusieurs raisons à cela :

  • Les pos­si­bi­li­tés étendues de trans­for­ma­tion al­gé­brique des pro­grammes.
  • De vastes pos­si­bi­li­tés en matière de synthèse al­gé­brique de pro­grammes.
  • Options simples d’analyse sé­man­tique grâce à l’éli­mi­na­tion des « états internes aux procédés de calcul » et des « effets se­con­daires ».
  • Éli­mi­na­tion des états internes : con­trai­re­ment à ce qui se passe en pro­gram­ma­tion im­pé­ra­tive, il n’est pas né­ces­saire de faire référence à des états internes dans les procédés de calcul.
  • Sup­pres­sion des effets se­con­daires : les chan­ge­ments d’état qui ap­par­tien­nent aux états internes, ce qu’on appelle les effets se­con­daires, peuvent également être supprimés dans le travail fonc­tion­nel.

La pro­gram­ma­tion fonc­tion­nelle offre un haut degré d’abs­trac­tion parce qu’elle s’appuie sur le principe ma­thé­ma­tique de la fonction. Utilisé de façon ap­pro­priée, ce type de pro­gram­ma­tion permet de générer un code très précis. Pour résoudre une tâche de grande ampleur, un programme a à sa dis­po­si­tion un très grand nombre d’unités beaucoup plus petites, uti­li­sables à plusieurs reprises et très spé­cia­li­sées : les fonctions.

Il existe donc des raisons pratiques qui ex­pli­quent pourquoi la pro­gram­ma­tion fonc­tion­nelle et les langages de pro­gram­ma­tion relevant de ce paradigme occupent encore aujourd’hui une place par­ti­cu­lière en in­for­ma­tique, en par­ti­cu­lier lorsqu’il s’agit de tâches ma­thé­ma­tiques complexes et d’al­go­rithmes. De plus, le caractère très spécial de ses domaines d’ap­pli­ca­tion garantit aux langages de pro­gram­ma­tion fonc­tion­nels une existence de niche.

En un coup d’œil : les langages de pro­gram­ma­tion fonc­tion­nelle les plus im­por­tants

Parmi les langages de pro­gram­ma­tion les plus im­por­tants basés sur l’approche fonc­tion­nelle, on retrouve les suivants :

  • LISP
  • ML
  • Haskell
  • OCaml
  • F#
  • Erlang
  • Clojure
  • Scala

De plus, il existe des langages de pro­gram­ma­tion connus qui au­to­ri­sent, entre autres nom­breuses pos­si­bi­li­tés, l’adoption d’un paradigme de pro­gram­ma­tion fonc­tion­nelle :

  • Perl
  • Ruby
  • Visual Basic .NET
  • Dylan
  • EC­MAS­cript

Ré­ca­pi­tu­la­tif des avantages et in­con­vé­nients liés à la pro­gram­ma­tion fonc­tion­nelle

Avantages In­con­vé­nients
Les pro­grammes n’ont pas d’état Les données (p. ex. variables) ne sont pas mo­di­fiables
Idéal pour la pa­ral­lé­li­sa­tion Il n’est pas possible de récupérer de façon efficace de grandes quantités de données
Code fa­ci­le­ment testable Non re­com­mandé pour connexion à des bases de données et serveurs
Code fa­ci­le­ment vé­ri­fiable : même les fonctions sans état peuvent être vérifiées Ne convient pas en cas de nom­breuses ré­cur­sions d'une même pile
Se combine bien avec une pro­gram­ma­tion im­pé­ra­tive et orientée objet La pro­gram­ma­tion récursive peut entraîner de graves erreurs
Code plus précis et concis Ne convient pas à toutes les tâches

Ce tableau donne un bon aperçu de la question de savoir si le paradigme fonc­tion­nel est l’approche ap­pro­priée pour un projet logiciel. Le choix d’un style de pro­gram­ma­tion dépend souvent des pré­fé­rences per­son­nelles du dé­ve­lop­peur. Ainsi, la pro­gram­ma­tion orientée objet est souvent préférée à l’approche fonc­tion­nelle par de nombreux pro­gram­meurs. Nous allons briè­ve­ment comparer ci-dessous les deux approches, en concluant sur un cas pratique.

Tendance ou pas ? Com­pa­rai­son croisée entre pro­gram­ma­tion orientée objet et pro­gram­ma­tion fonc­tion­nelle

Tout comme dans la mode, il existe en pro­gram­ma­tion de vé­ri­tables tendances. Cela fait un certain temps que la pro­gram­ma­tion orientée objet jouit d’une grande po­pu­la­rité, en par­ti­cu­lier dans le dé­ve­lop­pe­ment d’ap­pli­ca­tions Web et de jeux vidéo. Con­trai­re­ment à la pro­gram­ma­tion fonc­tion­nelle, cette approche ne décrit pas les éléments in­di­vi­duels comme des fonctions, mais en termes d’objets et de classes. Lorsqu’on programme sur un système ancien, cette approche présente un avantage certain : tous les com­po­sants peuvent être réu­ti­li­sés et étendus à tout moment, sans dif­fi­culté. De son côté, le code fonc­tion­nel est beaucoup plus simple et clair, ce qui se révèle par­ti­cu­liè­re­ment utile lorsqu’il faut vérifier et tester du code.

Ajoutons qu’il n’est pas forcément né­ces­saire de choisir entre pro­gram­ma­tion orientée objet et pro­gram­ma­tion fonc­tion­nelle. De nombreux langages de pro­gram­ma­tion modernes per­met­tent de tra­vail­ler si­mul­ta­né­ment avec les deux styles de pro­gram­ma­tion : il est alors possible de les combiner fa­ci­le­ment et de bé­né­fi­cier ainsi des avantages proposés par les deux pa­ra­digmes.

Exemple de pro­gram­ma­tion fonc­tion­nelle : le parseur

Les ana­ly­seurs syn­taxiques ou parseurs sont des éléments centraux à tous les pro­grammes in­for­ma­tiques. Ils se mettent au service des com­pi­la­teurs pour traduire le langage de pro­gram­ma­tion en langage machine et sont à ce titre souvent in­dis­pen­sables.

Il est possible de mettre en place un parseur en s’appuyant sur dif­fé­rents pa­ra­digmes de pro­gram­ma­tion - et donc, par exemple, avec un langage orienté objet. Cependant, l’approche fonc­tion­nelle offre un certain nombre d’avantages précieux lorsqu’il s’agit de concevoir le code d’un parseur.

  • Il n’existe pas de variables globales et mo­di­fiables. Par con­sé­quent, le risque de rencontre des erreurs de pro­gram­ma­tion liés à ce qu’on appelle un « mutable global state » (« état global mutable ») n’existe pas, con­trai­re­ment à ce qui peut se passer dans le cadre de projets orientés objet. C’est un état de fait favorable à l’éta­blis­se­ment d’un parseur en tant qu’élément central du programme.
  • Grâce à des fonctions d’ordre supérieur et à un code de pro­gram­ma­tion clair, il est possible de traiter fa­ci­le­ment des échan­til­lons de données encore plus im­por­tants. C’est un avantage certain pour un parseur, appelé par sa nature même à traiter de grandes quantités de données.
  • On exécute très souvent des parseurs dans le cadre de pro­grammes in­for­ma­tiques. Il est donc utile pour le dé­rou­le­ment de tout le programme que cet élément central soit programmé avec précision et fonc­tionne ef­fi­ca­ce­ment, comme c’est le cas en pro­gram­ma­tion fonc­tion­nelle.
  • Une erreur dans le processus d’analyse syn­taxique se révèle gé­né­ra­le­ment fatale, et il convient par con­sé­quent de les éviter autant que possible. Cependant, dans le cadre de l’exécution d’un programme, de nom­breuses dé­pen­dances sé­man­tiques font iné­vi­ta­ble­ment leur ap­pa­ri­tion, ce qui peut entraîner de graves erreurs - mais cela ne se produit la plupart du temps qu’après une durée d’exécution plus longue. Si elle est cor­rec­te­ment mise en œuvre, la pro­gram­ma­tion fonc­tion­nelle peut con­tri­buer à minimiser ou à prévenir com­plè­te­ment l’ap­pa­ri­tion d’erreurs de ce genre en cours d’exécution.
Aller au menu principal