Currying et application partielle en JavaScript
Le currying et l’application partielle sont des techniques puissantes de programmation fonctionnelle qui peuvent considérablement améliorer la modularité et la réutilisabilité de votre code JavaScript. Dans cet article, nous allons approfondir ces concepts, explorer leurs bonnes pratiques et fournir des exemples pratiques pour vous aider à maîtriser leur utilisation.
Comprendre le currying
Le currying est une technique qui transforme une fonction en une séquence de fonctions, chacune prenant un seul argument. Cela permet de décomposer une fonction qui prend plusieurs arguments en une série de fonctions unaires (à un seul argument).
Exemple de currying
Considérez une fonction simple qui additionne trois nombres :
function add(a, b, c) {
return a + b + c;
}Nous pouvons transformer cette fonction en une version curryfiée :
Explication :
- La fonction
addprend trois arguments et retourne leur somme. - La fonction
curryAddest une version curryfiée deadd. Elle prend un argumentaet retourne une autre fonction qui prendb. Cette deuxième fonction retourne encore une autre fonction qui prendc. La fonction la plus interne retourne la somme dea,betc.
Avantages du currying
- Réutilisabilité : Les fonctions curryfiées vous permettent de créer de nouvelles fonctions en fixant certains arguments. Cela améliore la réutilisabilité en vous permettant de créer facilement des versions spécialisées d’une fonction sans dupliquer le code.
Ici, curriedAdd est une version curryfiée de la fonction add. Elle nous permet de créer des fonctions spécialisées comme add5 en fixant le premier argument (a) à 5. Cela favorise la réutilisation du code, car nous pouvons créer plusieurs fonctions spécialisées sans répéter la logique d’addition.
- Composition de fonctions : Le currying facilite la composition de fonctions. La composition de fonctions est le processus qui consiste à combiner deux fonctions ou plus pour produire une nouvelle fonction.
Dans cet exemple, nous composons les fonctions multiply et addOne à l’aide du currying. En curryfiant ces fonctions, nous pouvons facilement créer une nouvelle fonction addOneThenMultiplyBy5, qui ajoute d’abord 1 à l’entrée (x), puis multiplie le résultat par 5. Cela montre comment le currying facilite la composition de fonctions, en simplifiant la création de nouvelles fonctions en combinant des fonctions existantes.
Implémenter le currying en JavaScript
Nous pouvons créer une fonction utilitaire pour curryfier n’importe quelle fonction. Voici une implémentation d’une fonction de currying générique :
Explication :
Fonction de currying (
curry) :- La fonction
curryprend une autre fonctionfnen entrée. - Elle retourne une nouvelle fonction appelée
curried. - Cette fonction
curriedprend n’importe quel nombre d’arguments à l’aide de la syntaxe du paramètre rest (...args).
- La fonction
Fonction curryfiée (
curried) :- À l’intérieur de
curried, elle vérifie si le nombre d’arguments fournis (args.length) est supérieur ou égal au nombre d’arguments attendus par la fonction originalefn(fn.length). - Si suffisamment d’arguments sont fournis, elle appelle la fonction originale
fnavec ces arguments en utilisantfn.apply(this, args). - Si les arguments sont insuffisants, elle retourne une nouvelle fonction qui accepte d’autres arguments (
nextArgs) à l’aide de l’opérateur de décomposition (...nextArgs). - Cette nouvelle fonction récursivement appelle
curriedavec les arguments combinés (args.concat(nextArgs)), en s’assurant que tous les arguments sont finalement collectés avant d’appeler la fonction originalefn.
Remarque :
fn.lengthcompte uniquement les paramètres sans valeurs par défaut et ignore les paramètres rest.- À l’intérieur de
Exemple d’utilisation :
- Nous définissons une fonction
multiplyqui prend trois arguments et retourne leur produit. - Nous créons une version curryfiée de la fonction
multiplyen la passant à la fonctioncurry, qui retourne une nouvelle fonctioncurriedMultiply. - Désormais,
curriedMultiplypeut être appelée avec un, deux ou trois arguments. - Chaque fois que nous appelons
curriedMultiplyavec un ou plusieurs arguments, elle retourne une nouvelle fonction jusqu’à ce que tous les arguments soient collectés, puis elle retourne le résultat de la multiplication des arguments entre eux.
- Nous définissons une fonction
Explorer l’application partielle
L’application partielle est une technique qui consiste à créer une nouvelle fonction en préremplissant certains arguments de la fonction originale. C’est particulièrement utile pour créer des fonctions spécialisées.
Exemple d’application partielle
Considérez la fonction suivante qui formate un message :
function formatMessage(greeting, name) {
return `${greeting}, ${name}!`;
}Nous pouvons créer une fonction partiellement appliquée :
Explication :
- La fonction
formatMessageprend deux arguments,greetingetname, et retourne un message formaté. - La fonction
partialprend une fonctionfnet quelques arguments prédéfinis (...presetArgs). Elle retourne une nouvelle fonction qui prend les arguments restants (...laterArgs). - Lorsque la nouvelle fonction est appelée, elle combine
presetArgsetlaterArgspuis appelle la fonction originalefnavec ces arguments. - En utilisant
partial, nous créonsgreetHello, une fonction qui utilise toujours "Hello" comme salutation. Lorsqu’elle est appelée avec un nom, elle retourne le message complet.
Avantages de l’application partielle
Simplification : Créer des fonctions plus simples à partir de fonctions plus complexes
Supposons que nous ayons une fonction qui calcule le prix final d’un article après application d’une remise et d’une taxe.
function calculateFinalPrice(price, discount, tax) {
return price - (price * discount) + (price * tax);
}Cette fonction nécessite trois arguments, ce qui la rend un peu fastidieuse à utiliser de manière répétée si les taux de remise et de taxe sont souvent les mêmes. Avec l’application partielle, nous pouvons simplifier cela.
Dans l’exemple ci-dessus, applyDiscountAndTax est une fonction partiellement appliquée qui préremplit les valeurs discount et tax. Cela facilite le calcul du prix final pour différents articles sans avoir à spécifier à chaque fois les taux de remise et de taxe.
Réutilisabilité du code : Réutiliser une logique de fonction commune avec différents arguments prédéfinis
Imaginez que nous ayons une fonction qui journalise des messages avec différents niveaux de gravité.
function logMessage(level, message) {
console.log(`[${level}] ${message}`);
}Nous pouvons créer des fonctions réutilisables pour différents niveaux de journalisation à l’aide de l’application partielle.
Ici, createLogger est une fonction partiellement appliquée qui définit l’argument level. Les fonctions infoLogger et errorLogger peuvent maintenant être utilisées pour journaliser des messages avec les niveaux prédéfinis, en réutilisant la logique commune de logMessage.
- Lisibilité améliorée : Rend le code plus lisible en décomposant les fonctions complexes Considérez une fonction qui formate des dates dans différents styles.
function formatDate(date, format) {
const options = { year: 'numeric', month: '2-digit', day: '2-digit' };
if (format === 'US') {
options.month = 'long';
} else if (format === 'EU') {
options.day = 'numeric';
options.month = 'numeric';
}
return new Date(date).toLocaleDateString(undefined, options);
}En utilisant l’application partielle, nous pouvons créer des fonctions plus lisibles pour différents formats de date.
createDateFormatter applique partiellement l’argument format, ce qui donne des fonctions spécifiques pour les formats de date US et EU. Cette décomposition rend le code plus lisible et plus facile à comprendre, car chaque formateur est dédié à un format particulier.
Ces exemples illustrent comment l’application partielle en JavaScript peut simplifier des fonctions complexes, améliorer la réutilisabilité du code et renforcer la lisibilité, rendant le code plus facile à gérer et à comprendre.
Bonnes pratiques pour utiliser le currying et l’application partielle
Garder des fonctions pures
- Veillez à ce que les fonctions curryfiées et partiellement appliquées restent pures, sans effets de bord. Cela les rend plus faciles à comprendre et à tester.
Utiliser lorsque c’est approprié
- Utilisez le currying et l’application partielle lorsqu’ils s’adaptent naturellement au problème à résoudre.
- Évitez d’abuser de ces techniques, car elles peuvent rendre le code plus difficile à comprendre si elles ne sont pas utilisées avec discernement.
Exploiter la composition de fonctions
- Combinez des fonctions curryfiées pour créer des fonctionnalités plus complexes. Le currying fonctionne bien avec la composition de fonctions, ce qui conduit à un code plus modulaire.
Documentation et nommage
- Documentez correctement les fonctions curryfiées et partiellement appliquées afin d’indiquer leur utilisation attendue.
- Utilisez des noms clairs et descriptifs pour les fonctions afin de transmettre leur objectif.
INFO
Si vous utilisez fréquemment le currying et l’application partielle, envisagez d’utiliser la bibliothèque Lodash, qui fournit des fonctions utilitaires pratiques comme _.curry et _.partial.
Combiner avec les méthodes de tableau
Le currying peut être efficacement combiné avec les méthodes de tableau comme map, filter et reduce pour un code concis et expressif.
Explication :
- La fonction
curriedMultiplyest utilisée pour créermultiplyByTwo, une fonction qui multiplie son argument par 2. - Le tableau
numbersest transformé à l’aide demap, en appliquantmultiplyByTwoà chaque élément, ce qui produit un nouveau tableau de nombres doublés.
Conclusion
Le currying et l’application partielle en JavaScript offrent des techniques puissantes pour simplifier la composition de fonctions, améliorer la réutilisabilité du code et renforcer la lisibilité. Le currying transforme des fonctions à plusieurs arguments en une série de fonctions unaires, permettant un code plus flexible et plus modulaire. L’application partielle permet de préconfigurer des arguments de fonction, facilitant la réutilisation du code et la simplification de fonctions complexes. En tirant parti de ces concepts de programmation fonctionnelle, les développeurs peuvent écrire un code JavaScript plus propre, plus concis et plus facile à maintenir.
Practice
What is correct about Currying in JavaScript?