La « mode » du fonctionnel : pourquoi ?
Vous avez déjà dû entendre parler de langages comme Haskell, Erlang, Clojure ou encore Scala (si ce n’est pas le cas, vous devez lire l’article encore plus que les autres). Twitter a refait son moteur de recherche en Scala et Facebook utilise Erlang pour son système de chat par exemple. Tous ces langages partagent un même paradigme (certains plus que d’autres, mais passons), et c’est en partie ce qui fait leur succès : le paradigme de programmation fonctionnelle. Je vais essayer de vous expliquer ici en quoi c’est plus qu’une mode ou une lubie d’universitaire barbu (ou non), et pourquoi donc vous devriez vous y intéresser.
Disclaimer : Je ne suis pas un expert en programmation fonctionnelle, je vous donne juste ici quelques raisons de s’y intéresser. Si les puristes y voient quelques absurdités, n’hésitez pas à me taper dessus.
Le bannissement des variables
Ça fait 10 ans que vous codez en impératif (vous avez bien fait un peu de prolog ou de OCaml à la fac mais ça ne compte pas vraiment), vous avez toujours fait des trucs dans le style i++ ou x = x + 1 et ça ne vous empêche pas de dormir, bien. C’est une honte (je fais style mais ça ne m’empêche toujours pas de dormir hein). Une des choses qui m’a le plus surpris quand j’ai appris le « pur » fonctionnel, c’est qu’on vous dit que vous ne pouvez ré-assigner une variable (qui n’est plus vraiment variable dans le coup).
Vous faites x = 1 et si vous essayez ensuite de faire x = 2 vous aurez une erreur, diantre. Et là vous vous dites : « Pourrrrrrrrquuuuuuuuuoooooooooooiiiiiiiiii est-il si méchant ? ». « Et mon for, je vais le faire comment moi ? ». Pas de panique, ça fait toujours ça la première fois.
Avant de vous dire pourquoi, juste une petite apartée vocabularistique. Vous entendrez parler de cette chose sous le terme de « données immutables ».
Pourquoi ?
Pourquoi est-ce que cette « restriction » est en fait une des clés du succès des langages fonctionnels ? Elle va permettre de faire des programmes concurrents (vous connaissez ça sous le terme multi-thread, mais il n’est pas adapté ici, car on n’utilise pas de thread dans le language) facilement, et donc de faire des programmes qui passent bien à l’échelle (scalable).
Si vous avez déjà essayé de faire joujou avec les threads, vous savez que l’accès aux données est problématique. Quand plusieurs threads veulent lire la même donnée en mémoire pas de soucis. Mais c’est quand plusieurs threads veulent modifier que ça pose problème. Qui doit avoir la priorité ? Comment fait-on quand une valeur a été modifiée par le thread 2 après que le thread 1 l’ait lue mais avant qu’il ait eu le temps de la ré-écrire ? Vos amis les sémaphores ne sont pas loin, et là c’est le drame de la complexité et des « dead locks ».
Et si on interdisait aux programmes de modifier une variable déjà affectée ? Nous y voilà. Avec cette restriction, les langages fonctionnels facilitent énormément le travail des développeurs.
Le gros mot du jour : transparence référentielle
Un des autres aspects qui différencie la programmation impérative de la programmation fonctionnelle est la transparence référentielle. En gros ça veut dire que si vous appelez 2 fois la même fonction avec les mêmes paramètres, elle doit toujours retourner la même valeur (et elle ne doit pas produire d’effets de bord, lisez le lien wikipédia).
C’est rarement le cas en programmation objet. Vous avez toujours des fonctions qui dépendent de l’état de l’objet. Si vous avez une fonction isEmpty() sur un objet et que vous l’appelez à plusieurs reprises sur un objet qui peut être plein ou vide, elle retournera un résultat différent en fonction de son état, à 2 moments différents du même programme. Elle n’est pas référentiellement transparente. Le fait de ne pas pouvoir modifier les variables aide clairement à avoir des fonctions transparentes référentiellement.
Pourquoi je vous parle de ça ? Imaginez vous avez des fonctions qui sont indépendantes les unes des autres, qui n’ont pas d’effets de bord, et qui ne partagent pas d’endroits en mémoire. Ça serait pas top de répartir tout ce petit monde sur des cœurs différents de votre processeur avec des systèmes tous prêts ? C’est notamment faisable par des modèles d’acteurs (en anglais dans le texte, la page française est un peu vide), disponibles directement en Scala ou Erlang.
Et mon for(i=0, …) alors ?
Certes vous allez devoir l’oublier (i est modifié à chaque itération). Mais vous apprendrez d’autres manières d’itérer sur vos collections (map et autres joyeusetés) qui vous semblerons finalement tout aussi naturelles. Ne prenez pas peur à la vue ces fonctions, elles vont vous permettre d’exprimer ce que vous souhaitez faire, au lieu de le décrire ligne par ligne ce que l’ordinateur doit faire en style impératif.
Voilà par exemple comment afficher les paroles de la chanson « Happy Birthday to You » en Scala sans boucle for.
(1 to 4).map { i => « Happy Birthday » + (if (i == 3) « dear Vince » else « to You ») }.foreach { println }
Conclusion
Je cherchais depuis un bout de temps ce qui pourrait me redonner le goût d’apprendre, et la programmation fonctionnelle a été un déclic pour moi. Passer de PHP à Ruby, à Python c’est sympa, mais ça reste le même paradigme de programmation, ça ne me faisait plus rêver. Avec la programmation fonctionnelle vous trouverez au mieux un nouvel eldorado, au pire vous verrez votre façon de coder en impératif différemment. Aller hop, au boulot !
Pour aller plus loin
Je vous ai mis l’eau à la bouche et vous avez vous aussi envie de découvir ce fabuleux monde. Voilà ce que je vous conseille (en anglais par contre, je vais pas pouvoir faire autrement) :
Haskell
C’est LE language purement fonctionnel. Si vous voulez vous y mettre pour de vrai (et souffrir pour de vrai), allez y pour celui-là. Pas sûr que vous ferez de vrais projets avec, mais c’est le langage vers lequel vous devriez tendre.
Il existe en plus un très bon livre, consultable sur internet (que je vous conseille d’acheter) : Learn You a Haskell For Great Good.
Erlang
Erlang est un langage fonctionel aussi, mais moins extrémiste qu’Haskell. Son système d’acteurs et sa philosophie « let it crash » sont très intéressants. Je ne l’ai pas encore assez approfondi pour pouvoir en dire plus pour l’instant.
Un petit livre accessible en ligne : Learn You Some Erlang For Great Good
Scala
C’est le moins fonctionnel de ma séléction. Et pour cause, vous pouvez utiliser des variables mutables (même si vous pouvez utiliser des immutables aussi) et de la programmation objet. C’est une sorte de langage hybride qui vous permet de faire du fonctionnel, tout en restant dans ce que vous connaissez (la POO). Il tourne en plus sur une JVM et est compatible avec les librairies Java déjà existantes … C’est à mon avis le plus pragmatique pour une utilisation en entreprise (compatibilité Java, possiblité de faire de l’OOP), mais le moins efficace pour apprendre le fonctionnel pour de vrai. C’est ce que nous utilisons dans ma boîte actuelle.
Des ressources sont disponibles sur le site, la référence restant le livre du fondateur du langage M. Odersky Programming in Scala, Second Edition ».
Tags: erlang, fonctionnel, haskell, scala
14 Réponses
Laisser un message


Bel article :)
Pour avoir fait du fonctionnel avec notamment du Scheme (purement dans un but d’apprentissage du fonctionnel) en cours et du Ocaml (mais presque sans l’autorisation d’utiliser des variables immuables), le fonctionnel c’est bien mais je préfère utiliser de la POO.
Je trouve la lecture d’un programme purement fonctionnel plus difficile qu’un autre itératif.
Par exemple, il est plus facile de lire
x = 1;
size = 25
for i in range(size):
x += i
print(x)
que de lire
def add(i, x, size):
if i < size-1:
return add(i+1, x+i, size)
else:
return x+i
size = 25
x = add(1, 1, size)
print x
Pourtant ces programmes font la même choses (et dans le même langage : python)
Notons également que même si rien ne l'oblige, il est possible de faire du pure fonctionnel avec un language objet (e.g. du php)
Dans le cas de ruby, c'est un peu différent puisque même les types de bases (entiers, booléens, etc.) sont des objets.
en scala je vais préférer faire :
print ((1 to 25).reduceLeft(_ + _))
ou
print((1 to 25).foldLeft(0) { (total, x) => total + x }
ou tout simplement
print((1 to 25).sum)
Niveau concision, à toi de voir ;) Python n’a pas toutes les subtilités des « vrais » langages fonctionnels je suppose. Faire du fonctionnel, ce n’est pas juste utiliser des fonctions, c’est un façon de penser à changer !
Oui je suis d’accord avec toi que python n’est pas le langage le plus approprié pour faire du fonctionnel.
Dans le cas précis que j’ai donné print((1 to 25).sum) est une belle facile fonctionnelle de le faire.
Ceci dit, avec un exemple plus complexe, je pense pas que ce soit le cas.
La version print((1 to 25).foldLeft(0) { (total, x) => total + x } n’est pas la plus lisible que la version itérative que j’ai donné.
Après, c’est aussi une question d’habitude. Il est clair et net que j’ai pas autant d’habitude avec du fonctionnel que de l’itétatif ;-)
C’est clairement une histoire d’habitude. La version avec le fold était incompréhensible pour moi au début, maintenant c’est bien plus simple et limpide que les versions que tu proposes.
C’est purement et simplement une fonction d’apprentissage et d’habitude.
Quand tu y penses, for i in range(size): x += i n’est pas ce qu’il y a de plus lisible non plus, pour un débutant en impératif.
Bref, au bout d’un mois, il y a moyen de comprendre les principales subtilités du fonctionnel, cad être capable d’au moins suivre du code en le lisant.
Remarque python est bien loti en fonctionnel aussi, avec les compréhensions de liste notamment.
Et en python j’aurais bien fait un truc comme ça :
print(sum(range(25)))
Pas besoin de variable mutable ;)
Bonjour,
Avec des objets immutables sur du multi-thread on va travailler sur plusieurs instances du même objets. Par exemple, ça donnerait un « map/list » à 3 entrée. La première ce serait une donnée qui est éligible pour être supprimée. La seconde ça serait celle qui est accessible. La troisième ça serait celle qui est ajoutée et ainsi de suite. C’est une mécanique facile à faire en itératif, alors je ne vois pas bien l’apport du langage fonctionnel.
J’avais fait de l’Ocaml en IUT, pour jouer un peu avec ce langage j’avais fait un petit puissance 4 sur la console/invite de commande. Par apport à du C de l’époque, pour moi l’Ocaml était clairement illisible. Je trouve même le Cobol plus facile à lire pourtant c’est verbeux.
De façon générale, plus c’est compliqué à écrire, plus c’est compliqué à maintenir. Personnellement je tablerais plus en entreprise sur le Java que sur le Scala.
Par ailleurs sur des technologies web moderne (tablettes, téléphone portable, etc…), ce qu’il est préconisé, c’est d’économiser la mémoire avec la ré-utilisation de variables. Ça donne l’impression d’un retour en arrière avec le vieux C/C++.
Tout est faisable en itératif, la preuve en est des technologies web actuelles. Est-ce une raison pour s’y cantonner ? Pas sûr.
« De façon générale, plus c’est compliqué à écrire, plus c’est compliqué à maintenir. » Ce n’est ici qu’une question d’habitude. Fais-en pour de vrai pendant quelques mois, et tu trouveras ça tout aussi facile.
Si tu vas par là, plus il y a de lignes de code plus il y a de possiblités de bugs, donc le fonctionnel est moins buggé ;) (troll inside)
« Personnellement je tablerais plus en entreprise sur le Java que sur le Scala. » J’ai envie de dire ça dépendra de ta boîte. Je préférerai embaucher des mecs qui trouvent que Scala a un vrai intérêt, plutôt qu’un expert J2EE.
Pour moi le développement spécifique pour des « tablettes, téléphone portable, etc » est une régression, partant de là … Ces types de langage sont plus adaptés au backend à mon avis.
Allez, pour dire :)
Un sémaphore qui est donc mon ami.
Un petit bout de code, juste pour la boucle for, aurait été le bienvenu pour les geeks que la littérature ne repaît pas :p
greg
Pardi, j’ai toujours cru que Sémaphore était féminin. Je suis tout chose. Je m’en vais modifier ça de suite.
http://www.amicalement-web.net/la-mode-du-fonctionnel-pourquoi/2012/01/02/comment-page-1/#comment-31666
Tu as des exemples de code dans mon commentaire si tu veux. Tu as de bons examples qui claquent ici : http://mkaz.com/solog/scala/10-scala-one-liners-to-impress-your-friends.html
Comment imprimer les paroles de la chanson « Happy Birthday To You » par exemple sans for ;)
(1 to 4).map { i => « Happy Birthday » + (if (i == 3) « dear NAME » else « to You ») }.foreach { println }
En échangeant avec d’autres développeurs sur les Jug Java, justement sur le thème du langage fonctionnel et du Scala, déjà il est peu utiliser et il intéresse peu de développeur. Le seul qui s’y était vraiment mis, nous a dit qu’il avait déjà eu des difficultés à l’apprendre et surtout à le maintenir. De plus il ne le voyait pas arriver en entreprise, enfin pas dans un futur proche. Ca m’a rappelé quand j’avais tenté de faire un peu de fun avec l’Ocaml.
Dans l’informatique en ce moment il vaut mieux être un expert Java EE, qu’un expert Scala, il suffit de regarder les annonces. Le jour où le marché change et s’oriente vers le fonctionnel, je m’y replongerais mais pour l’instant, j’ai rien à y gagner.
Juger quelqu’un sur le simple fait qu’il programme en fonctionnel, aura plus de valeur qu’un expert en itératif, je trouve ça plutôt réducteur comme critère. Je préfère avoir une personne autonome, qui s’adapte vite au client, au projet et à l’entreprise, plutôt qu’un spécialiste limiter et/ou borner. Le langage ce n’est qu’un détail technique, comme je dis à chaque fois au nouveau 3 jours pour apprendre le langage, 3 ans pour le maitriser.
Sur les « nouvelles technologies », je vois qu’on partage le même point de vue. Des fois je me dis sur les téléphone portable/tablette, autant programmer en C++ comme ça on enlève le garbage collector et on joue avec les pointeurs, comme au bon vieux temps (ou pas ^^).
« Dans l’informatique en ce moment il vaut mieux être un expert Java EE, qu’un expert Scala, » Je pense exactement le contraire, tout dépend du Job que tu veux.
Je ne veux pas le Job que les autres ont, je veux celui pour lequel je prendrai plaisir à travailler. Et ça marche. Ya 10 ans j’ai choisi de ne pas faire de J2EE du tout, et je m’en porte très bien.
« il suffit de regarder les annonces » Justement, moins la technologie est utilisée, plus je me fais plaisir. Dès qu’il y aura trop d’annonces Scala, il sera temps de changer.
« Je préfère avoir une personne autonome, qui s’adapte vite au client, au projet et à l’entreprise, » Moi je veux juste un dev qui aime ce qu’il fait. Si c’est du fonctionnel très bien, de l’objet très bien, du moment que ça fait le boulot et que le gars s’éclate.
« Juger quelqu’un sur le simple fait qu’il programme en fonctionnel, aura plus de valeur qu’un expert en itératif, je trouve ça plutôt réducteur comme critère. » Qui a dit ça ? Je juge un dev sur son ouverture d’esprit et sur sa capacité à se tenir à jour, pas sur le fait que ça fait 10 ans qu’il s’est perdu dans du J2EE.
Bref, à chacun sa vision je suppose ;)
Tout d’abord merci pour cet article, la programmation fonctionelle mérite d’être mieux connue.
J’ai découvert la fp depuis peu, 6 mois environ, j’ai commencer par apprendre haskell par le livre de Richard Bird (introduction to functional programming using Haskell), ce fut vraiment ardu, entre les mathématiques et la programmation, très intéressant mais épuisant, je suis à la moitié ;)
J’ai acheter aussi real world in haskell, vraiment intéressant car rapidement on arrive à appréhender la logique fonctionnel, depuis j’ai vraiment l’impression de penser différemment l’informatique, c’est chelou !
les types , les monads , les parsers combinators, les lists, les tuples, le pattern matching , les folds ( au début c’est vrai que c’est illisible mais au bout de quelques mois cela devient comme tu le dis très clair) amène à avoir une autre approche de la programmation.
En ce moment je suis aussi sur scala, je fais un dev au taff notamment pour les parsers, la gestion du xml( se rapproche un peu du xquery) et le fait que cela fonctionne sur une jre, plus facile à faire passer en entreprise que haskell.
les points forts de scala : les actors (inspiré de erlang), les définitions implicites qui permettent de réaliser des dsl facilement, les call by name des paramètres, le système de typage fort, le mélange oo-fp qui modélise bien les données(oo) et leurs interaction (fp). Je vous conseille le bouquin de odersky, une véritable bible !!)
Bref, si vous avez un peu de temps ( car ça en bouffe bcp ) ça vaut vraiment le coup d’essayer de coder en fp.
Hello,
Juste pour répondre au commentaire a propos de Scala qui et utiliser par personne et pas en entreprise…
C’est a mon avis complétement faux: Ils vous suffit de checker les offres d’emplois scala sur Londres.
On trouve également de plus en plus de job Scala en Suisse, ça fait personellement plus de 7 mois que je fait du Scala tout les jours au boulot.
Les grands aussi: Twitter, Facebook, LinkedIn recrute des devs Scala.
Je pense qu’il faut garder a l’esprit que maitriser des languages tel que Scala/Clojure/Haskell vous différencie nettement de l’énorme masse de développeur J2EE.
Et je trouve ça plutôt agréable :-)
Je vous recommende le liver « Programing In Scala » que est disponible gratuitement dans ça première édition:
http://www.artima.com/pins1ed/
A+
Alois Cochard
Ah la programmation fonctionnelle!
Je m’étais bien régalé à l’époque en cours de fac en utilisant le langage Scheme.