C'est un paradigme différent de la programmation impérative "classique", ce qui implique :
Intérêt ?
Apprendre Haskell permet d'écrire de meilleurs programmes, même dans d'autres langages.
function diviserParDeux(nombre) {
var missile = lancerUnMissileNucleaire();
fairePorterLeChapeauAuDrManhattan(missile);
return nombre / 2;
}
Cette fonction a des effets de bord observables qu'on ne peut pas deviner en regardant sa valeur de retour. Il faut donc faire constamment attention lorsqu'on la manipule !
function ajouterCinq(nombre) {
return nombre + 5;
}
Cette fonction n'a pas d'effets de bord. Elle renvoie toujours le même résultat lorsqu'on l'appelle avec les mêmes arguments.
ajouterCinq(-4) == ajouterCinq(-4)
Le résultat du programme ne change pas si on remplace une expression par une expression de valeur équivalente.
Utiliser des fonctions pures permet de raisonner sur son programme comme sur une équation.
La logique métier est fiable, sans surprise et aisément testable.
On sait quelles fonctions ont des effets de bord, ce qui permet d’être prudent lorsqu’on les manipule.
En JS, les fonctions sont des objets de première classe (first-class citizen).
Une fonction d’ordre supérieur est une fonction qui possède au moins l'une des propriétés suivantes :
function appliquerDeuxFois(f, x) {
return f(f(x));
}
// ^ accepte une fonction en paramètre
function foisTrois(x) {
return x * 3;
}
appliquerDeuxFois(foisTrois, 7);
// --> (7 * 3) * 3 = 63
On va voir un exemple concret : les opérations sur les tableaux en JS.
var villes = [
{ nom: "Nantes", dep: 44, mer: false },
{ nom: "Dunkerque", dep: 59, mer: true },
{ nom: "Paris", dep: 75, mer: false },
];
On veut obtenir une liste de chaines de type ville (dep)
.
On va écrire une fonction rendreVillesAffichables
telle que :
rendreVillesAffichables(villes);
// --> ["Nantes (44)", "Dunkerque (59)",
// "Paris (75)"]
function rendreVillesAffichables(villes) {
for (var i = 0; i < villes.length; i++) {
villes[i] = villes[i].nom +
" (" + villes[i].dep + ")";
}
return villes;
}
On mélange 2 comportements :
function rendreVillesAffichables(villes) {
function transformation(ville) {
return ville.nom +
" (" + ville.dep + ")";
}
return villes.map(transformation);
}
Array.map
gère le parcours du tableau \o/villes.filter(function(item) {
// Si la ville est près de la mer,
// on renvoie true, sinon false
return item.mer;
});
// --> [ { nom: "Dunkerque", dep: 59,
// mer: true }
villes.filter(function(item) {
return !item.mer;
}).map(function(item) {
return item.nom + " (" + item.dep + ")";
});
// --> ["Nantes (44)", "Paris (75)"]
Rappel : Array.map
et Array.filter
sont des fonctions d'ordre supérieur.
var personnes = [
{ nom: "Bruce", age: 30 },
{ nom: "Tony", age: 35 },
{ nom: "Peter", age: 26 },
];
personnes.reduce(function(acc, cur) {
return acc + cur.age;
}, 0);
// --> 91
function map(tableau, transformation) {
return tableau.reduce(function(acc, cur) {
acc.push(transformation(cur));
return acc;
}, []);
}
function filter(tableau, predicat) {
return tableau.reduce(function(acc, cur) {
if (predicat(cur)) acc.push(cur);
return acc;
}, []);
}
Si vous avez un tableau et que vous voulez :
La programmation fonctionnelle offre de belles manières d'écrire des programmes fiables et maintenables.
Twitter : @d_sferruzza
Slides sur GitHub :