La programmation fonctionnelle : un exemple concret pour comprendre comment ça marche

programmation fonctionnelle

La programmation fonctionnelle : un exemple concret pour comprendre comment ça marche

Share on twitter
Share on linkedin
Share on pinterest
Share on reddit
Share on pocket
Share on email

La programmation fonctionnelle est un paradigme de programmation peu répandu, bien qu’ancien, car il tire ses racines du lambda calculus. Ce paradigme a gagné en popularité sur la dernière décennie avec l’avènement du big data, pour des raisons que nous allons voir dans cet article.

Avant de commencer, qu’est-ce qu’un paradigme de programmation ? 

Il s’agit d’une approche, d’une méthodologie pour construire des programmes informatiques indépendamment du langage utilisé. Un paradigme est constitué entre autres de règles et de principes. 

Les paradigmes les plus connus : procédural, orienté objet et fonctionnel

La programmation procédurale et la programmation orientée objet sont les deux paradigmes les plus répandus (et de loin).

Programmation procédurale

La programmation procédurale est généralement le premier paradigme que l’on apprend, le plus simple. Il s’agit d’une séquence d’instructions s’exécutant les unes après les autres. Ces instructions peuvent être regroupées par blocs dans des fonctions.

Cette approche montre rapidement ses limites au fur et à mesure qu’un programme grandit. Elle est donc cantonnée à des programmes relativement courts (mais potentiellement complexes).

Programmation orientée objet

La programmation orientée objet est probablement le paradigme le plus répandu dans l’industrie. Un programme orienté objet se compose d’objets auxquels sont associés des attributs et des méthodes.

Par exemple, dans un logiciel de comptabilité, un compte sera un objet, le solde de ce compte sera un attribut du même objet et l’action de réaliser une transaction sera une méthode qui peut être appelée pour modifier le compte.

Cette forme d’abstraction est très intéressante pour des programmes de taille importante, car elle permet un découpage par blocs logiques proche du réel.

Programmation fonctionnelle

Moins répandue, mais tout de même considérée comme un paradigme majeur, la programmation fonctionnelle s’inspire des fonctions mathématiques. 

Ce paradigme est beaucoup plus abstrait. L’entité centrale est la fonction, au sens mathématique du terme, donc définie par une expression donnée telle que : 

                                                                   f(x, y) = x + y

(à ne pas confondre avec la fonction en programmation procédurale, qui est un outil pratique pour regrouper des instructions).

La programmation fonctionnelle est régie par plusieurs concepts majeurs tels que les fonctions pures, l’immuabilité… Cet article n’a pas pour but de détailler chacun de ces principes, mais de présenter un cas concret. Si vous souhaitez cependant en apprendre plus après lecture de l’exemple ci-dessous, ce post relativement court représente une première introduction à ces principes.

Un exemple concret pour comprendre la programmation fonctionnelle

Pour mieux comprendre, prenons un exemple et comparons une approche procédurale avec une approche fonctionnelle.

Notre problème : faire le solde d’une liste de transactions

Imaginons trois personnes : Riri, Fifi, Loulou. Elles s’échangent souvent de l’argent entre elles et ont une trace écrite de chaque transaction. 

Voici la liste de leurs transactions :

Elles aimeraient bien savoir quel est le solde de leurs comptes respectifs à tout instant. Pour ce faire, nous allons construire un petit programme pour calculer ce solde à une date donnée.

Approche procédurale

Dans un premier temps, adoptons une approche procédurale (en Python) :

On commence par définir la date à laquelle on souhaite calculer le solde. Puis, on initialise les soldes à 0 pour chacun des trois.

Ensuite, on boucle sur toutes les transactions, de sorte à :

  • vérifier la date d’une transaction, si elle est trop récente on l’ignore ;
  • mettre à jour les soldes en fonction du montant, de l’émetteur et du destinataire de chaque transaction.

À la fin, la variable soldes contient le solde des trois personnes à la date donnée.

Cette approche est probablement la plus directe et la plus simple pour cet exemple volontairement simpliste.

Approche fonctionnelle

Voyons maintenant à quoi ce programme pourrait ressembler avec une approche fonctionnelle :

Nous définissons plusieurs fonctions qui nous permettront d’appliquer des transformations à nos transactions initiales :

  • Les premières fonctions servent à filtrer les transactions pour ne garder que celles qui nous intéressent (par exemple, filtrer_date permet de garder les transactions antérieures à une date donnée).
  • La fonction prendre_montant applique à chaque transaction une même opération, à savoir, extraire le montant de la transaction.
  • La fonction somme opère une réduction. Une réduction permet d’agréger les éléments d’une liste. Dans ce cas, les éléments sont les montants des transactions et l’opération réalisée est la somme de ces montants.
  • Enfin, calculer_solde est une fonction combinant les fonctions précédentes pour pouvoir déterminer le solde de l’une des trois personnes à une date donnée.

Quels avantages pour la programmation fonctionnelle ?

Assurément, l’approche procédurale semble beaucoup plus simple dans ce cas précis. Mais regardons plus en détail le code de l’approche fonctionnelle : on remarque qu’il n’y a aucune assignation de variable (à l’inverse du code procédural où on assigne et réassigne plusieurs fois la variable soldes).

De fait, le code en programmation fonctionnelle n’a aucun état, aussi bien local que global (à part l’état lié aux données initiales, qui reste inchangé). 

C’est l’un des grands avantages de la programmation fonctionnelle, car :

  • cela évite les effets de bords, ainsi, une fonction renvoie toujours le même résultat pour une entrée donnée, indépendamment de l’état du système – ce qui permet de mettre le résultat en cache et simplifie le débogage – ;
  • les opérations peuvent être réalisées indépendamment les unes des autres. En effet, avec les fonctions Map, Reduce ou Filter, le résultat sera le même quel que soit l’ordre de la liste en entrée. Cela rend facile la parallélisation de ce code.

C’est pour ces raisons que la programmation fonctionnelle est particulièrement appréciée en big data, la parallélisation est en effet nécessaire pour traiter de tels volumes de données. Ce paradigme est justement à la base de certains outils de big data tels que MapReduce ou Spark, dont nous parlions déjà dans cet article.

Demo
Demandez votre
démo de Saagie !