Recherche…
Remarques
Qu'est-ce que la programmation fonctionnelle?
La programmation fonctionnelle ou PF est un paradigme de programmation qui repose sur deux concepts principaux: l' immuabilité et l' apatridie . Le but de la PF est de rendre votre code plus lisible, réutilisable et portable.
Qu'est-ce que le JavaScript fonctionnel?
Il y a eu un débat pour appeler JavaScript un langage fonctionnel ou non. Cependant, nous pouvons absolument utiliser JavaScript comme une fonctionnalité en raison de sa nature:
- A des fonctions pures
- A des fonctions de première classe
- A la fonction d'ordre supérieur
- Il supporte l' immuabilité
- A des fermetures
- Méthodes de récursion et de liste (tableaux) comme la carte, réduire, filtrer ..etc
Les exemples doivent couvrir chaque concept en détail, et les liens fournis ici sont fournis à titre de référence et doivent être supprimés une fois le concept illustré.
Accepter des fonctions comme arguments
function transform(fn, arr) {
let result = [];
for (let el of arr) {
result.push(fn(el)); // We push the result of the transformed item to result
}
return result;
}
console.log(transform(x => x * 2, [1,2,3,4])); // [2, 4, 6, 8]
Comme vous pouvez le voir, notre fonction de transform
accepte deux paramètres, une fonction et une collection. Il va ensuite itérer la collection, et pousser les valeurs sur le résultat, appelant fn
sur chacun d'eux.
Semble familier? Ceci est très similaire à la façon dont Array.prototype.map()
fonctionne!
console.log([1, 2, 3, 4].map(x => x * 2)); // [2, 4, 6, 8]
Fonctions d'ordre supérieur
En général, les fonctions qui opèrent sur d’autres fonctions, en les prenant comme arguments ou en les retournant (ou les deux), sont appelées fonctions d’ordre supérieur.
Une fonction d'ordre supérieur est une fonction qui peut prendre une autre fonction en argument. Vous utilisez des fonctions d'ordre supérieur lors du passage de rappels.
function iAmCallbackFunction() {
console.log("callback has been invoked");
}
function iAmJustFunction(callbackFn) {
// do some stuff ...
// invoke the callback function.
callbackFn();
}
// invoke your higher-order function with a callback function.
iAmJustFunction(iAmCallbackFunction);
Une fonction d'ordre supérieur est également une fonction qui renvoie une autre fonction en tant que résultat.
function iAmJustFunction() {
// do some stuff ...
// return a function.
return function iAmReturnedFunction() {
console.log("returned function has been invoked");
}
}
// invoke your higher-order function and its returned function.
iAmJustFunction()();
Identité Monad
Ceci est un exemple d'implémentation de la monade d'identité en JavaScript et pourrait servir de point de départ pour créer d'autres monades.
Basé sur la conférence de Douglas Crockford sur les monades et les gonades
En utilisant cette approche, il sera plus facile de réutiliser vos fonctions grâce à la flexibilité offerte par cette monade et aux cauchemars de composition:
f(g(h(i(j(k(value), j1), i2), h1, h2), g1, g2), f1, f2)
lisible, agréable et propre:
identityMonad(value)
.bind(k)
.bind(j, j1, j2)
.bind(i, i2)
.bind(h, h1, h2)
.bind(g, g1, g2)
.bind(f, f1, f2);
function identityMonad(value) {
var monad = Object.create(null);
// func should return a monad
monad.bind = function (func, ...args) {
return func(value, ...args);
};
// whatever func does, we get our monad back
monad.call = function (func, ...args) {
func(value, ...args);
return identityMonad(value);
};
// func doesn't have to know anything about monads
monad.apply = function (func, ...args) {
return identityMonad(func(value, ...args));
};
// Get the value wrapped in this monad
monad.value = function () {
return value;
};
return monad;
};
Il fonctionne avec des valeurs primitives
var value = 'foo',
f = x => x + ' changed',
g = x => x + ' again';
identityMonad(value)
.apply(f)
.apply(g)
.bind(alert); // Alerts 'foo changed again'
Et aussi avec des objets
var value = { foo: 'foo' },
f = x => identityMonad(Object.assign(x, { foo: 'bar' })),
g = x => Object.assign(x, { bar: 'foo' }),
h = x => console.log('foo: ' + x.foo + ', bar: ' + x.bar);
identityMonad(value)
.bind(f)
.apply(g)
.bind(h); // Logs 'foo: bar, bar: foo'
Essayons tout:
var add = (x, ...args) => x + args.reduce((r, n) => r + n, 0),
multiply = (x, ...args) => x * args.reduce((r, n) => r * n, 1),
divideMonad = (x, ...args) => identityMonad(x / multiply(...args)),
log = x => console.log(x),
substract = (x, ...args) => x - add(...args);
identityMonad(100)
.apply(add, 10, 29, 13)
.apply(multiply, 2)
.bind(divideMonad, 2)
.apply(substract, 67, 34)
.apply(multiply, 1239)
.bind(divideMonad, 20, 54, 2)
.apply(Math.round)
.call(log); // Logs 29
Fonctions pures
Un principe de base de la programmation fonctionnelle est qu’elle évite de changer l’état de l’application (état d’apatridie) et les variables en dehors de sa portée (immuabilité).
Les fonctions pures sont des fonctions qui:
- avec une entrée donnée, retourne toujours la même sortie
- ils ne s'appuient sur aucune variable en dehors de leur champ d'application
- ils ne modifient pas l'état de l'application ( pas d'effets secondaires )
Jetons un coup d'oeil à quelques exemples:
Les fonctions pures ne doivent changer aucune variable en dehors de leur portée
Fonction impure
let obj = { a: 0 }
const impure = (input) => {
// Modifies input.a
input.a = input.a + 1;
return input.a;
}
let b = impure(obj)
console.log(obj) // Logs { "a": 1 }
console.log(b) // Logs 1
La fonction a modifié la valeur obj.a
qui est hors de sa portée.
Fonction pure
let obj = { a: 0 }
const pure = (input) => {
// Does not modify obj
let output = input.a + 1;
return output;
}
let b = pure(obj)
console.log(obj) // Logs { "a": 0 }
console.log(b) // Logs 1
La fonction n'a pas changé les valeurs d' obj
objet
Les fonctions pures ne doivent pas s'appuyer sur des variables hors de leur portée
Fonction impure
let a = 1;
let impure = (input) => {
// Multiply with variable outside function scope
let output = input * a;
return output;
}
console.log(impure(2)) // Logs 2
a++; // a becomes equal to 2
console.log(impure(2)) // Logs 4
Cette fonction impure repose sur la variable a
définie en dehors de sa portée. Donc, si un est modifié, le résultat de la fonction impure
sera différent.
Fonction pure
let pure = (input) => {
let a = 1;
// Multiply with variable inside function scope
let output = input * a;
return output;
}
console.log(pure(2)) // Logs 2
Le résultat de la fonction pure
ne repose sur aucune variable en dehors de sa portée.