Programmation fonctionnelle : idéale pour les algorithmes

Les langages de programmation les plus courants permettent généralement d’utiliser des paradigmes de programmation différents. Il est ainsi possible d’établir de manière générale une distinction entre programmation déclarative et programmation impérative. Pour simplifier, ces paradigmes définissent l’approche de base adoptée par les logiciels de programmation. La programmation dite fonctionnelle relève d’une approche déclarative. Elle est utilisée en particulier dans le développement des programmes ou codes suivants :

  • applications techniques et mathématiques
  • intelligence artificielle (IA)
  • compilateurs et parseurs
  • algorithmes

Dans quoi réside l’intérêt lié au paradigme fonctionnel dans le cadre de ce type d’application informatique ? Et quelle est la différence avec des concepts comme la programmation orientée objet ?

Qu’est-ce que la programmation fonctionnelle ?

Comme son nom l’indique, l’approche fonctionnelle de la programmation se concentre sur la notion de fonctions. Dans un programme fonctionnel, tous les éléments peuvent être compris comme des fonctions et le code peut être exécuté par des appels successifs de fonctions. À l’inverse, aucune valeur n’est assignée de façon indépendante. On peut se représenter une fonction comme étant la variante spéciale d'un sous-programme donné. Elle est réutilisable et, contrairement à une procédure, renvoie directement un résultat.

Bien sûr, dans de nombreux langages de programmation évolués, il existe des fonctions qui sont définies puis appliquées. Il ne s'agit donc pas de la particularité principale de la programmation fonctionnelle. Ce qui rend l'approche fonctionnelle si importante pour l'informatique et qui fait toute sa polyvalence, c'est le fait que les fonctions de ce paradigme de programmation peuvent prendre différentes « formes ». Par exemple, elles peuvent être associées entre elles comme des données. Elles peuvent également être utilisées en tant que paramètres et résultats de fonctions. Ce traitement spécial des fonctions permet aux programmeurs de mettre en place et de traiter des tâches de calcul de grande envergure (en particulier celles qui relèvent d’une nature symbolique).

Pourquoi la programmation fonctionnelle est plus que jamais d’actualité

Bien que les racines de la programmation fonctionnelle remontent aux années 1930 (dans le cadre de la recherche mathématique fondamentale), l’approche fonctionnelle jouit encore d’une grande popularité, surtout dans les domaines techniques et en mathématiques. Il y a plusieurs raisons à cela :

  • Les possibilités étendues de transformation algébrique des programmes.
  • De vastes possibilités en matière de synthèse algébrique de programmes.
  • Options simples d’analyse sémantique grâce à l’élimination des « états internes aux procédés de calcul » et des « effets secondaires ».
  • Élimination des états internes : contrairement à ce qui se passe en programmation impérative, il n’est pas nécessaire de faire référence à des états internes dans les procédés de calcul.
  • Suppression des effets secondaires : les changements d’état qui appartiennent aux états internes, ce qu’on appelle les effets secondaires, peuvent également être supprimés dans le travail fonctionnel.

La programmation fonctionnelle offre un haut degré d’abstraction parce qu’elle s’appuie sur le principe mathématique de la fonction. Utilisé de façon appropriée, ce type de programmation permet de générer un code très précis. Pour résoudre une tâche de grande ampleur, un programme a à sa disposition un très grand nombre d’unités beaucoup plus petites, utilisables à plusieurs reprises et très spécialisées : les fonctions.

Il existe donc des raisons pratiques qui expliquent pourquoi la programmation fonctionnelle et les langages de programmation relevant de ce paradigme occupent encore aujourd’hui une place particulière en informatique, en particulier lorsqu’il s’agit de tâches mathématiques complexes et d’algorithmes. De plus, le caractère très spécial de ses domaines d’application garantit aux langages de programmation fonctionnels une existence de niche.

En un coup d’œil : les langages de programmation fonctionnelle les plus importants

Parmi les langages de programmation les plus importants basés sur l’approche fonctionnelle, on retrouve les suivants :

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

De plus, il existe des langages de programmation connus qui autorisent, entre autres nombreuses possibilités, l’adoption d’un paradigme de programmation fonctionnelle :

  • Perl
  • Ruby
  • Visual Basic .NET
  • Dylan
  • ECMAScript

Récapitulatif des avantages et inconvénients liés à la programmation fonctionnelle

Avantages Inconvénients
Les programmes n’ont pas d’état Les données (p. ex. variables) ne sont pas modifiables
Idéal pour la parallélisation Il n’est pas possible de récupérer de façon efficace de grandes quantités de données
Code facilement testable Non recommandé pour connexion à des bases de données et serveurs
Code facilement vérifiable : même les fonctions sans état peuvent être vérifiées Ne convient pas en cas de nombreuses récursions d'une même pile
Se combine bien avec une programmation impérative et orientée objet La programmation 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 fonctionnel est l’approche appropriée pour un projet logiciel. Le choix d’un style de programmation dépend souvent des préférences personnelles du développeur. Ainsi, la programmation orientée objet est souvent préférée à l’approche fonctionnelle par de nombreux programmeurs. Nous allons brièvement comparer ci-dessous les deux approches, en concluant sur un cas pratique.

Tendance ou pas ? Comparaison croisée entre programmation orientée objet et programmation fonctionnelle

Tout comme dans la mode, il existe en programmation de véritables tendances. Cela fait un certain temps que la programmation orientée objet jouit d’une grande popularité, en particulier dans le développement d’applications Web et de jeux vidéo. Contrairement à la programmation fonctionnelle, cette approche ne décrit pas les éléments individuels 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 composants peuvent être réutilisés et étendus à tout moment, sans difficulté. De son côté, le code fonctionnel est beaucoup plus simple et clair, ce qui se révèle particulièrement utile lorsqu’il faut vérifier et tester du code.

Ajoutons qu’il n’est pas forcément nécessaire de choisir entre programmation orientée objet et programmation fonctionnelle. De nombreux langages de programmation modernes permettent de travailler simultanément avec les deux styles de programmation : il est alors possible de les combiner facilement et de bénéficier ainsi des avantages proposés par les deux paradigmes.

Exemple de programmation fonctionnelle : le parseur

Les analyseurs syntaxiques ou parseurs sont des éléments centraux à tous les programmes informatiques. Ils se mettent au service des compilateurs pour traduire le langage de programmation en langage machine et sont à ce titre souvent indispensables.

Il est possible de mettre en place un parseur en s’appuyant sur différents paradigmes de programmation - et donc, par exemple, avec un langage orienté objet. Cependant, l’approche fonctionnelle 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 modifiables. Par conséquent, le risque de rencontre des erreurs de programmation liés à ce qu’on appelle un « mutable global state » (« état global mutable ») n’existe pas, contrairement à ce qui peut se passer dans le cadre de projets orientés objet. C’est un état de fait favorable à l’établissement d’un parseur en tant qu’élément central du programme.
  • Grâce à des fonctions d’ordre supérieur et à un code de programmation clair, il est possible de traiter facilement des échantillons de données encore plus importants. 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 programmes informatiques. Il est donc utile pour le déroulement de tout le programme que cet élément central soit programmé avec précision et fonctionne efficacement, comme c’est le cas en programmation fonctionnelle.
  • Une erreur dans le processus d’analyse syntaxique se révèle généralement fatale, et il convient par conséquent de les éviter autant que possible. Cependant, dans le cadre de l’exécution d’un programme, de nombreuses dépendances sémantiques font inévitablement leur apparition, 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 correctement mise en œuvre, la programmation fonctionnelle peut contribuer à minimiser ou à prévenir complètement l’apparition d’erreurs de ce genre en cours d’exécution.