La composition de fonction grâce au "Currying"

Le currying est une méthode de composition pour écrire des fonctions pures et n'ayant qu'une responsabilité. La composition est de plus en plus à la mode en ce moment grace à certains frameworks JavaScript comme React, mais je suis toujours surpris aujourd'hui que beaucoup de développeurs Front ne la connaissent pas.

Je vais tenter de vous expliquer simplement et rapidement ce que c'est et comment s'en servir.

Le currying pour les nulls

Une fonction "curried" ou qui a été écrite en suivant le principe de currying est une fonction qui ne peut prendre qu'un seul argument. C'est la règle de base dont on ne peut déroger. Comment faire si l'on a besoin de plus d'arguments ?

La composition est la méthode utilisée pour répondre à cette question. Les fonctions "curried" retournent souvent d'autres fonctions. Prenons un exemple :

function add(a) {
    return function (b) {
        return a + b
    }
}

add(1)(2) === 3 // true

C'est un exemple qui n'a aucun autre but que de montrer rapidement la composition en currying, on est d'accord. Mais il a le mérite d'être clair. (Si vous souhaitez d'autres exemples de currying en JavaScript ou dans d'autres languages, la page wikipédia en regorge.)

Une fonction ne peut prendre qu'un seul argument et si l'on a besoin de deux arguments : on utilise deux fonctions.

En optimisant un peu, il est possible d'écrire l'exemple ci-dessus de façon plus courte :

const add = a => b => a + b

Pourquoi faire du currying ?

Il peut être difficile de s'en rendre compte avec l'exemple que j'ai donné mais le currying peut être très utile ! Déjà, il est utile dans tous les cas où la composition l'est.

Ensuite, il peut clairement simplifier notre code. Ou... peut-être pas le simplifier mais le rendre plus compréhensible grâce à la séparation des responsabilités.

Il est à noter que les fonctions "curried" doivent être pures. Si la fonction add ne retournait jamais la même chose pour un même argument, il serait totalement inutile de faire du currying.

const add = a => b => a + b
const addTen = add(10)
const addTwo = add(2)

addTen(40) === 50 // true
addTwo(2) === 4 // true

Encore une fois, le code de l'exemple n'a pour but que l'illustration de mes propos. Et j'espère que maintenant vous voyez ce que je veux dire par  "le rendre (le code) plus compréhensible".

Vous n'êtes pas obligé d'utiliser les fonctions "curried" directement depuis leur premier niveau. Vous pouvez les "découper" en plusieurs fonctions qui, grâce au nom que vous leur donnerez, ont un sens et une responsabilité beaucoup plus claire dans leur contexte immédiat.

Un autre petit point qui pourrait vous pousser à essayer le currying est la rigueur qu'il exige. C'est une méthodologie, comme une figure de style lorsque vous faites des langues, vous pouvez l'utiliser uniquement comme un kata — exercice pour vous pousser dans vos retranchement — et apprendre encore plus sur le language.

Et puis, si vous faites ça, vous serez beaucoup plus à l'aise lorsque vous rencontrerez ce genre de code au détour d'un bug à corriger.


Pour allez plus loin :