Image par Mogmi.

Mon dernier article laissait penser que je reprenais goût pour la programmation fonctionnelle, ayant apprécié mes études à bases d’OCaml. Depuis, j’ai effectivement eu l’occasion de jouer avec Scala, avec Haskell. Je ne suis pas spécialement un pro-FP ou un anti-POO, ni même l’inverse. Ce qui m’intéresse, ce sont les enjeux derrière chaque paradigme. Que vais-je pouvoir tirer de telle ou telle techno ? Au fond, qu’est-ce que je veux vraiment faire ?

Why learning Haskell/Python makes you a worse programmer ?

L’auteur évoque ses difficultés de revenir à la réalité, à la réalité du Python, du C#, du Java ou du C++ (pour les plus chanceux). Je vais dans ce billet donner mon point de vue. De la philosophie de la programmation fonctionnelle, je retiens notamment la gestion des listes et structures récursives, le pattern matching, l’immutabilité, les monades, la lazy-evaluation. J’en oublie, mais ce sont là les éléments que j’estime utiliser régulièrement, au naturel.

Sans prétention, la manipulation de ces concepts fait que le programmeur acquière une certaine gymnastique qui n’est — à mon sens — que bénéfique. Gestion de la concurrence ? Modularité ? Travail en équipe avec d’autres adeptes de la FP ? Du bonheur. Je ne parle pas spécialement de performances, mais seulement d’architecture logicielle.

Seulement voilà, dans la vraie vie, difficile de débarquer, imposer une industrialisation de Haskell ou d’OCaml. Difficile de dire à des développeurs ayant l’habitude d’imbriquer trois niveaux de boucles for ou while de réfléchir par récursion. Difficile de remettre en question les modélisations objets de projets industrialisés recoupant plusieurs dizaines ou centaines de développeurs, sous prétexte que de nombreux bugs pourraient être évités en appliquant des mécanismes d’immutabilité.

C’est bien là le problème. Renouer avec les fonctions impures à outrance (se dit des fonctions à effet de bord), les API approximatives de Java ou PHP n’est pas synonyme de plaisir. L’argument de la « démotivation » lancé par Luke sur son blog est réel. On écrit du code bizarre, rien n’est séduisant.

En revanche, j’estime que ça me force à comprendre comment le langage fonctionne, et à ne jamais faire confiance à son fonctionnement. En 2 mois de temps, j’ai appris un nombre impressionnant de choses sur Java, notamment sur sa gestion de la concurrence (faut-il que je me sente honteux de tout juste découvrir que le langage propose des CountdownLatch ?) En tout état de cause, c’est mon arme contre la démotivation.

Un compromis intéressant me semble émaner de Scala. Son interopérabilité parfaite (?) avec Java lui donne l’avantage instantané de participer à toutes les logiques d’industrialisation. Scala, pour rappel, est un langage multi-paradigme, qui aime la POO autant que la FP ou l’AOP. Un méli-mélo, vous dîtes ? C’est sans doute vrai. Et je n’aime pas les mélanges incohérents, vraiment pas. Mais en pratique, force est de constater que, pour le moment, c’est un moyen assez élégant de faire en sorte que chacun puisse y trouver son compte. Il m’est arrivé, par exemple, de parcourir un graphe en Scala et d’appliquer un traitement en une ligne de code, via le paradigme map/reduce (mais pas distribué, cette fois-ci). Scala peut également obliger les développeurs à formaliser leurs types de retours en Option[Integer] si la fonction peut retourner l’équivalent de null ; tout en conservant la possibilité d’écrire des boucles itératives aux moments opportuns, ou de modéliser ses concepts sous formes de classes, sans rien changer — ou presque — des habitudes prises en Java.

Oh, et tant qu’on en parle, je vous invite à lire le billet de Marwan sur la FP. C’est aussi un élément déclencheur de cet article.

, ,

.
Une guise de petite entrée en matière, laissez moi vous faire compiler une ligne :
factorielle n = product[1..n]

Un tel snippet semblera peut-être quelque peu ambitieux pour ceux qui ne jurent que par la programmation impérative. PHP, Java, C++ et consort. C’est pourtant une ligne parfaitement valide en Haskell. Bienvenue dans l’univers de la programmation fonctionnelle. On ne gère plus des changements d’états, mais des évaluations de fonctions.

Des bouquins

C’est un univers que j’avais découvert avec OCaml durant mes classes prépa, et voilà que je replonge dedans. La « faute » à un excellent bouquin, « Hasard et complexité en mathématiques », écrit par Grégory-J Chaitin, le découvreur du nombre oméga « Ω » – mon nombre préféré, mais ce n’est pas le sujet ici.

Hasard et complexités en mathématiques

Dans son ouvrage, Grégory Chaitin avoue son amour sans nom à Lisp, un des plus anciens langages apportant le paradigme de programmation fonctionnelle. Un amour qu’il a ma foi su fort bien communiquer puisqu’il ma donné envie de remettre en questions mes développements actuels.

J’étais assez rebuté par la lisibilité du code en Lisp et après pas mal de lectures auxiliaires, je découvre à quel point Haskell est séduisant autant dans ses concepts que dans sa syntaxe. Gérer des ensembles infinis, ou des nombres à précision potentiellement infinie n’est sans doute pas une situation que tous les développeurs rencontrent tous les jours, mais c’est toujours source de nombreux problèmes dès que le cas fait surface. Ceux qui aiment les problématiques de typage seront ravis d’apprendre que Haskell est, parait-il, muni d’un système de typage à toute épreuve. J’aurai sans doute l’occasion de vous en dire un peu plus une fois mon apprentissage approfondi. Toujours est-il que j’ai commandé au monsieur tout-en-rouge le livre de la collection d’O'Reilly :

Haskell Oreilly
Voir sur O’Reilly

Un autre langage, qui fait sans doute plus parler de lui : Scala. Comme OCaml, il est multi-paradigme. Utilisé notamment chez Twitter, LinkedIn, Foursquare ou d’autres grands noms de la toile, on peut sûrement expliquer cette nouvelle popularité par son interopérabilité avec Java. Le langage fonctionne en effet tout aussi bien sous forme de scripts que de bytecode compilé à destination de la JVM, et il est en ce sens possible – et aisé – d’exécuter du code Java depuis Scala. Sans avoir encore trop farfouillé, j’ai tout de même l’impression que l’approche est assez différente de ce qu’on retrouve en Haskell ; j’ai ainsi constaté que beaucoup de codes ne pouvait s’offrir le luxe de faire l’impasse sur le cas des valeurs null. Peut-être du travail à faire du côté des monades ? J’en saurai sûrement davantage après une vraie découverte du langage et une lecture approfondie de cette autre idée cadeau :

Haskell Oreilly
Voir sur O’Reilly

Pourquoi quitter le monde impératif ?

Pourquoi un attrait si soudain pour la programmation fonctionnelle ? Pourquoi devriez-vous essayer, à votre tour, de voir autrement vos suites de 0 et de 1 ? En ce qui me concerne, le livre de Grégory Chaitin fut le véritable élément déclencheur, mais c’est aussi le désir de remettre plein de choses en question, de continuer à se maintenir éveillé sur ce qui se fait de nouveau (Scala), et peut-être de reprendre davantage de plaisir à développer en utilisant de nouvelles approches lorsque cela est nécessaire.

Je suis par exemple régulièrement amené à développer de nouveaux outils statistiques (des simples moyennes arithmétiques ou harmoniques aux matrices de covariance) et il n’est pas rare d’observer que le langage fait parfois partie integrante du problème que de la solution, pour reprendre l’expression de certains auteurs : dépassement de capacité des types integer et assimilés ; jonglage fréquent entre types signés, non signés, flottants ; impossibilité de redéfinir l’opérateur « + » dans certains langages, etc.

Je ne sais pas vraiment ce que j’attends de la programmation fonctionnelle dans mon usage quotidien, ou si Haskell sera strictement supérieur à Scala dans mon cas ou s’il sera juste un complément pertinent. Des concepts tels que les flèches me laissent penser que mes systèmes hautement concurrents pourraient s’en retrouver un peu plus concis et formels qu’avec les actuels langages impératifs. Alors, je vous donne rendez-vous pour de prochains billets pour de nouvelles critiques !

, , , , , ,