SlideShare a Scribd company logo
Programmation
fonctionnelle en
JavaScript
Loïc Knuchel
The Obvious
“La programmation fonctionnelle est une manière de programmer
principalement basée sur des fonctions”
The Headache
“La programmation fonctionnelle est un style de développement qui promeut
les fonctions indépendantes de l’état du programme.”
The One
“La programmation fonctionnelle permet de coder de manière plus modulaire
et plus productive, avec moins de code et moins de bugs”
FP is magic !
Transformer un tableau
var names = ['Finn', 'Rey', 'Poe', 'Kaylo'];
function upperCaseArray(arr){
var ret = [];
for(var i=0; i<arr.length; i++){
ret[i] = arr[i].toUpperCase();
}
return ret;
}
console.log(upperCaseArray(names));
// ['FINN', 'REY', 'POE', 'KAYLO']
Transformer un tableau
var names = ['Finn', 'Rey', 'Poe', 'Kaylo'];
function upperCaseArray(arr){
var ret = [];
for(var i=0; i<arr.length; i++){
ret[i] = arr[i].toUpperCase();
}
return ret;
}
console.log(upperCaseArray(names));
// ['FINN', 'REY', 'POE', 'KAYLO']
function upperCaseArray(arr){
return arr.map(function(item){
return item.toUpperCase();
});
}
Créer son .map()
Array.prototype.map = function(callback){
var array = this;
var result = [];
for(var i=0; i<array.length; i++){
result[i] = callback(array[i]);
}
return result;
};
Collection API
Traiter des données complexes
var claims = [{
wan: '123',
actions: [
{name: 'sendPicture', pictures: [
{path: '123/1.jpg', deleted: true, sync: false},
{path: '123/2.jpg', deleted: false, sync: true},
]},
{name: 'changeStep', step: 'COM'},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: false, sync: true},
{path: '123/4.jpg', deleted: false, sync: true}
]},
{name: 'sendPicture', pictures: [
{path: '123/5.jpg', deleted: true, sync: false},
{path: '123/6.jpg', deleted: false, sync: false}
]}
]
}, {
wan: '456',
actions: [
{name: 'sendPicture', pictures: [
{path: '456/1.jpg', deleted: false, sync: true},
{path: '456/2.jpg', deleted: false, sync: true},
]},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: true, sync: false},
{path: '123/4.jpg', deleted: true, sync: false}
]}
]
}];
Traiter des données complexes
var claims = [{
wan: '123',
actions: [
{name: 'sendPicture', pictures: [
{path: '123/1.jpg', deleted: true, sync: false},
{path: '123/2.jpg', deleted: false, sync: true},
]},
{name: 'changeStep', step: 'COM'},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: false, sync: true},
{path: '123/4.jpg', deleted: false, sync: true}
]},
{name: 'sendPicture', pictures: [
{path: '123/5.jpg', deleted: true, sync: false},
{path: '123/6.jpg', deleted: false, sync: false}
]}
]
}, {
wan: '456',
actions: [
{name: 'sendPicture', pictures: [
{path: '456/1.jpg', deleted: false, sync: true},
{path: '456/2.jpg', deleted: false, sync: true},
]},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: true, sync: false},
{path: '123/4.jpg', deleted: true, sync: false}
]}
]
}];
function doSomething(claims){
var pictures = [];
for(var i=0; i<claims.length; i++){
var claim = claims[i];
for(var j=0; j<claim.actions.length; j++){
var action = claim.actions[j];
if(action.name === 'sendPicture'){
for(var k=0; k<action.pictures.length; k++){
var picture = action.pictures[k];
if(!picture.deleted && !picture.sync){
pictures.push(picture);
}
}
}
}
}
return pictures;
}
Traiter des données complexes
var claims = [{
wan: '123',
actions: [
{name: 'sendPicture', pictures: [
{path: '123/1.jpg', deleted: true, sync: false},
{path: '123/2.jpg', deleted: false, sync: true},
]},
{name: 'changeStep', step: 'COM'},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: false, sync: true},
{path: '123/4.jpg', deleted: false, sync: true}
]},
{name: 'sendPicture', pictures: [
{path: '123/5.jpg', deleted: true, sync: false},
{path: '123/6.jpg', deleted: false, sync: false}
]}
]
}, {
wan: '456',
actions: [
{name: 'sendPicture', pictures: [
{path: '456/1.jpg', deleted: false, sync: true},
{path: '456/2.jpg', deleted: false, sync: true},
]},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: true, sync: false},
{path: '123/4.jpg', deleted: true, sync: false}
]}
]
}];
function doSomething(claims){
var pictures = [];
for(var i=0; i<claims.length; i++){
var claim = claims[i];
for(var j=0; j<claim.actions.length; j++){
var action = claim.actions[j];
if(action.name === 'sendPicture'){
for(var k=0; k<action.pictures.length; k++){
var picture = action.pictures[k];
if(!picture.deleted && !picture.sync){
pictures.push(picture);
}
}
}
}
}
return pictures;
}
Traiter des données complexes (lodash)
function getPicturesToSync(claims){
var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; }));
var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function
(action){ return action.pictures; }));
return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;});
}
Traiter des données complexes (lodash)
function getPicturesToSync(claims){
var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; }));
var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function
(action){ return action.pictures; }));
return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;});
}
_.map(array, callback) crée un tableau avec les valeurs retournées par le callback en paramètre.
Traiter des données complexes (lodash)
function getPicturesToSync(claims){
var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; }));
var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function
(action){ return action.pictures; }));
return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;});
}
_.flatten(array) crée un tableau simple à partir d’un tableau de tableaux.
Traiter des données complexes (lodash)
function getPicturesToSync(claims){
var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; }));
var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function
(action){ return action.pictures; }));
return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;});
}
_.filter(array, callback) crée un tableau en gardant que les éléments pour lesquels le callback renvoi true.
Traiter des données complexes (lodash)
function getPicturesToSync(claims){
var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; }));
var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function
(action){ return action.pictures; }));
return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;});
}
Traiter des données complexes (lodash)
function getPicturesToSync(claims){
var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; }));
var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function
(action){ return action.pictures; }));
return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;});
}
Traiter des données complexes (lodash)
function getPicturesToSync(claims){
var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; }));
var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function
(action){ return action.pictures; }));
return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;});
}
Traiter des données complexes (lodash)
function getPicturesToSync(claims){
var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; }));
var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function
(action){ return action.pictures; }));
return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;});
}
Améliorer les tableaux JavaScript
Array.prototype.find = function(callback){ return _.find(this, callback); }
Array.prototype.filter = function(callback){ return _.filter(this, callback); }
Array.prototype.map = function(callback){ return _.map(this, callback); }
Array.prototype.flatten = function() { return _.flatten(this); }
Traiter des données complexes (js array)
function getPicturesToSync(claims){
return claims
.map(function(claim){ return claim.actions; })
.flatten()
.filter(function(action){ return action.name === 'sendPicture'; })
.map(function(action){ return action.pictures; })
.flatten()
.filter(function(picture){ return picture.deleted === false && picture.sync === false;});
}
Traiter des données complexes (es6 fat arrow)
function getPicturesToSync(claims){
return claims
.map(claim => claim.actions)
.flatten()
.filter(action => action.name === 'sendPicture')
.map(action => action.pictures)
.flatten()
.filter(picture => picture.deleted === false && picture.sync === false);
}
Traiter des données complexes (pluck)
function getPicturesToSync(claims){
return claims
.map('actions')
.flatten()
.filter({name: 'sendPicture'})
.map('pictures')
.flatten()
.filter({deleted: false, sync: false});
}
Traiter des données complexes (flatMap)
var data = [
{id: '1', values: [1, 2, 3]},
{id: '2', values: [4, 5]},
];
data.map('values'); // [[1, 2, 3], [4, 5]]
data.map('values').flatten(); // [1, 2, 3, 4, 5]
Traiter des données complexes (flatMap)
Array.prototype.flatMap = function(callback){ return _.flatten(_.map(this, callback)); }
var data = [
{id: '1', values: [1, 2, 3]},
{id: '2', values: [4, 5]},
];
data.map('values'); // [[1, 2, 3], [4, 5]]
data.map('values').flatten(); // [1, 2, 3, 4, 5]
data.flatMap('values'); // [1, 2, 3, 4, 5]
Traiter des données complexes (flatMap)
function getPicturesToSync(claims){
return claims
.flatMap('actions')
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false, sync: false});
}
function getPicturesToSync(claims){
return claims
.flatMap('actions')
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false, sync: false});
}
Bilan
function getPicturesToSync(claims){
var pictures = [];
for(var i=0; i<claims.length; i++){
var claim = claims[i];
for(var j=0; j<claim.actions.length; j++){
var action = claim.actions[j];
if(action.name === 'sendPicture'){
for(var k=0; k<action.pictures.length; k++){
var picture = action.pictures[k];
if(!picture.deleted && !picture.sync){
pictures.push(picture);
}
}
}
}
}
return pictures;
}
function getPicturesToSync(claims){
return claims
.flatMap('actions')
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false, sync: false});
}
● moins de code
● moins de bugs
● plus de productivité
Bilan
function getPicturesToSync(claims){
var pictures = [];
for(var i=0; i<claims.length; i++){
var claim = claims[i];
for(var j=0; j<claim.actions.length; j++){
var action = claim.actions[j];
if(action.name === 'sendPicture'){
for(var k=0; k<action.pictures.length; k++){
var picture = action.pictures[k];
if(!picture.deleted && !picture.sync){
pictures.push(picture);
}
}
}
}
}
return pictures;
}
Autre exemple
var claims = [{
wan: '123',
actions: [
{name: 'sendPicture', pictures: [
{path: '123/1.jpg', deleted: true, sync: false},
{path: '123/2.jpg', deleted: false, sync: true},
]},
{name: 'changeStep', step: 'COM'},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: false, sync: true},
{path: '123/4.jpg', deleted: false, sync: true}
]},
{name: 'sendPicture', pictures: [
{path: '123/5.jpg', deleted: true, sync: false},
{path: '123/6.jpg', deleted: false, sync: false}
]}
]
}, {
wan: '456',
actions: [
{name: 'sendPicture', pictures: [
{path: '456/1.jpg', deleted: false, sync: true},
{path: '456/2.jpg', deleted: false, sync: true},
]},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: true, sync: false},
{path: '123/4.jpg', deleted: true, sync: false}
]}
]
}];
function doSomething(claims, wan){
return claims
.find({wan: wan}).actions
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false});
}
Autre exemple
var claims = [{
wan: '123',
actions: [
{name: 'sendPicture', pictures: [
{path: '123/1.jpg', deleted: true, sync: false},
{path: '123/2.jpg', deleted: false, sync: true},
]},
{name: 'changeStep', step: 'COM'},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: false, sync: true},
{path: '123/4.jpg', deleted: false, sync: true}
]},
{name: 'sendPicture', pictures: [
{path: '123/5.jpg', deleted: true, sync: false},
{path: '123/6.jpg', deleted: false, sync: false}
]}
]
}, {
wan: '456',
actions: [
{name: 'sendPicture', pictures: [
{path: '456/1.jpg', deleted: false, sync: true},
{path: '456/2.jpg', deleted: false, sync: true},
]},
{name: 'sendPicture', pictures: [
{path: '123/3.jpg', deleted: true, sync: false},
{path: '123/4.jpg', deleted: true, sync: false}
]}
]
}];
function doSomething(claims, wan){
return claims
.find({wan: wan}).actions
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false});
}
Bilan
function getPictures(claims, wan){
for(var i=0; i<claims.length; i++){
var claim = claims[i];
if(claim.wan === wan){
var pictures = [];
for(var j=0; j<=claim.actions.length; j++){
var action = claim.actions[i];
if(action.name === 'sendPicture'){
for(var k=0; k<action.pictures.length; k++){
var picture = action.pictures[k];
if(picture.deleted){
pictures.push(picture);
}
}
}
}
return pictures;
}
}
}
function getPictures(claims, wan){
return claims
.find({wan: wan}).actions
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false});
}
Bilan
function getPictures(claims, wan){
for(var i=0; i<claims.length; i++){
var claim = claims[i];
if(claim.wan === wan){
var pictures = [];
for(var j=0; j<=claim.actions.length; j++){
var action = claim.actions[i];
if(action.name === 'sendPicture'){
for(var k=0; k<action.pictures.length; k++){
var picture = action.pictures[k];
if(picture.deleted){
pictures.push(picture);
}
}
}
}
return pictures;
}
}
}
function getPictures(claims, wan){
return claims
.find({wan: wan}).actions
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false});
}
Bilan (correct)
function getPictures(claims, wan){
for(var i=0; i<claims.length; i++){
var claim = claims[i];
if(claim.wan === wan){
var pictures = [];
for(var j=0; j<claim.actions.length; j++){
var action = claim.actions[j];
if(action.name === 'sendPicture'){
for(var k=0; k<action.pictures.length; k++){
var picture = action.pictures[k];
if(!picture.deleted){
pictures.push(picture);
}
}
}
}
return pictures;
}
}
}
function getPictures(claims, wan){
return claims
.find({wan: wan}).actions
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false});
}
Bilan
La programmation fonctionnelle permet de
déclarer des intentions.
function getPictures(claims, wan){
return claims
.find({wan: wan}).actions
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false});
}
function getPicturesToSync(claims){
return claims
.flatMap('actions')
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false, sync: false});
}
Bilan
La programmation fonctionnelle permet de
déclarer des intentions.
Au final, on ne sait pas vraiment ce qui est fait
et quand.
function getPictures(claims, wan){
return claims
.find({wan: wan}).actions
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false});
}
function getPicturesToSync(claims){
return claims
.flatMap('actions')
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false, sync: false});
}
Bilan
La programmation fonctionnelle permet de
déclarer des intentions.
Au final, on ne sait pas vraiment ce qui est fait
et quand.
Ce qui permet de changer le fonctionnement
du programme sans changer le code.
function getPictures(claims, wan){
return claims
.find({wan: wan}).actions
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false});
}
function getPicturesToSync(claims){
return claims
.flatMap('actions')
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false, sync: false});
}
Bilan
La programmation fonctionnelle permet de
déclarer des intentions.
Au final, on ne sait pas vraiment ce qui est fait
et quand.
Ce qui permet de changer le fonctionnement
du programme sans changer le code.
Ex:
● synchrone => asynchrone
● impératif => lazy (cf Lazy.js)
function getPictures(claims, wan){
return claims
.find({wan: wan}).actions
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false});
}
function getPicturesToSync(claims){
return claims
.flatMap('actions')
.filter({name: 'sendPicture'})
.flatMap('pictures')
.filter({deleted: false, sync: false});
}
Quelques autres fonctions de lodash
● groupBy _.groupBy(claims[0].actions, function(action){
return action.name;
});
/* Result :
{
'sendPicture': [
{name: 'sendPicture', pictures: [...]},
{name: 'sendPicture', pictures: [...]},
{name: 'sendPicture', pictures: [...]}
],
'changeStep': [
{name: 'changeStep', step: 'COM'}
]
}
*/
Quelques autres fonctions de lodash
● groupBy
● partition
_.partition([1, 2, 3], function(n){
return n % 2;
});
// Result : [[1, 3], [2]]
Quelques autres fonctions de lodash
● groupBy
● partition
● sortBy
_.sortBy([2, 3, 1], function(n){
return n;
});
// Result : [1, 2, 3]
Quelques autres fonctions de lodash
● groupBy
● partition
● sortBy
● take / drop
_.take([1, 2, 3, 4, 5], 3); // Result : [1, 2, 3]
_.drop([1, 2, 3, 4, 5], 1); // Result : [2, 3, 4, 5]
Quelques autres fonctions de lodash
● groupBy
● partition
● sortBy
● take / drop
● uniq
_.uniq(['foo', 'bar', 'foo', 'foo']);
// Result : ['foo', 'bar']
_.uniq([{wan: '1'}, {wan: '2'}, {wan: '1'}], 'wan');
// Result : [{wan: '1'}, {wan: '2'}]
Quelques autres fonctions de lodash
● groupBy
● partition
● sortBy
● take / drop
● uniq
● reduce
_.reduce(claims, function(count, claim){
return count + claim.actions.length;
}, 0);
// Result: 6
Quelques autres fonctions de lodash
● groupBy
● partition
● sortBy
● take / drop
● uniq
● reduce
● sum / min / max
_.sum(['Finn', 'Rey', 'Poe', 'Kaylo'], function(name){
return name.length;
});
// Result : 15
Quelques autres fonctions de lodash
● groupBy
● partition
● sortBy
● take / drop
● uniq
● reduce
● sum / min / max
● ...
Basics
No side effect
Effets de bord: lancer une exception/erreur, faire un appel (bdd, http, fichier…), récupérer la date
actuelle, modifier un paramètre, accéder à une variable “globale”, mettre un log
Stateless
local reasoning
Immutability
Bénéfices
● Moins de code (~÷3 par rapport à Java)
● Plus compréhensible
● Plus facile à réutiliser / composer
● Plus facile à tester
● Moins de bugs
Exemple: Afficher ces données dans un graph
var data = [
{
name: "Jamestown",
population: 2047,
temperatures: [-34, 67, 101, 87]
},
{
name: "Awesome Town",
population: 3568,
temperatures: [-3, 4, 9, 12]
},
{
name: "Funky Town",
population: 1000000,
temperatures: [75, 75, 75, 75, 75]
}
];
// Result :
[
[55.25, 2047], // [average temperature, population]
[5.5, 3568],
[75, 1000000]
]
Code impératif
function formatChart(data){
var coords = [],
totalTemp = 0,
averageTemp = 0;
for(var i=0; i < data.length; i++){
totalTemp = 0;
for(var j=0; j < data[i].temperatures.length; j++){
totalTemp += data[i].temperatures[j];
}
averageTemp = totalTemp / data[i].temperatures.length;
coords.push([averageTemp, data[i].population]);
}
return coords;
}
Code impératif
function formatChart(data){
var coords = [],
totalTemp = 0,
averageTemp = 0;
for(var i=0; i < data.length; i++){
totalTemp = 0;
for(var j=0; j < data[i].temperatures.length; j++){
totalTemp += data[i].temperatures[j];
}
averageTemp = totalTemp / data[i].temperatures.length;
coords.push([averageTemp, data[i].population]);
}
return coords;
}
● Pas réutilisable
● Difficile à comprendre
● bugs probables
Functionnal way : sommer les températures
var totalTemp = totalForArray(0, temperatures);
// recursive to avoid loop
function totalForArray(currentTotal, arr){
if(arr.length === 0){
return currentTotal;
} else {
return totalForArray(currentTotal + arr[0], arr.slice(1));
}
}
Functionnal way : sommer les températures
var totalTemp = totalForArray(0, temperatures);
// recursive to avoid loop
function totalForArray(currentTotal, arr){
if(arr.length === 0){
return currentTotal;
} else {
return totalForArray(currentTotal + arr[0], arr.slice(1));
}
}
Vs
function totalForArray(currentTotal, arr){
return arr.reduce((total, item) => total + item, currentTotal);
}
Functionnal way : calculer la température moyenne
function average(total, count){
return total / count;
}
Functionnal way : calculer la température moyenne
function average(total, count){
return total / count;
}
function averageForArray(arr){
return average(totalForArray(0, arr), arr.length);
}
Functionnal way : calculer la température moyenne
function average(total, count){
return total / count;
}
function averageForArray(arr){
return average(totalForArray(0, arr), arr.length);
}
var averageTemp = averageForArray(temperatures);
Functionnal way : récupérer les températures
var allTemperatures = data.map(function(item){
return item.temperatures;
});
var data = [
{
name: "Jamestown",
population: 2047,
temperatures: [-34, 67, 101, 87]
},
{
name: "Awesome Town",
population: 3568,
temperatures: [-3, 4, 9, 12]
},
{
name: "Funky Town",
population: 1000000,
temperatures: [75, 75, 75, 75, 75]
}
];
Functionnal way : récupérer les températures
var allTemperatures = data.map(function(item){
return item.temperatures;
});
// simplify & shorten map syntax
function getItem(propertyName){
return function(item){
return item[propertyName];
}
}
var allTemperatures = data.map(getItem('temperature'));
var data = [
{
name: "Jamestown",
population: 2047,
temperatures: [-34, 67, 101, 87]
},
{
name: "Awesome Town",
population: 3568,
temperatures: [-3, 4, 9, 12]
},
{
name: "Funky Town",
population: 1000000,
temperatures: [75, 75, 75, 75, 75]
}
];
Curryfication
function add1(b){
return 1+b;
}
console.log(add1(2)); // 3
function addCurry(a){
return function(b){
return a+b;
}
}
var add1 = addCurry(1);
var add2 = addCurry(2);
console.log(add1(2)); // 3
console.log(add2(2)); // 4
Functionnal way : récupérer les températures
var allTemperatures = data.map(function(item){
return item.temperatures;
});
// simplify & shorten map syntax
function getItem(propertyName){
return function(item){
return item[propertyName];
}
}
var allTemperatures = data.map(getItem('temperature'));
var data = [
{
name: "Jamestown",
population: 2047,
temperatures: [-34, 67, 101, 87]
},
{
name: "Awesome Town",
population: 3568,
temperatures: [-3, 4, 9, 12]
},
{
name: "Funky Town",
population: 1000000,
temperatures: [75, 75, 75, 75, 75]
}
];
Functionnal way : récupérer les températures
var allTemperatures = data.map(function(item){
return item.temperatures;
});
// simplify & shorten map syntax
function getItem(propertyName){
return function(item){
return item[propertyName];
}
}
var allTemperatures = data.map(getItem('temperature'));
// more concise again !
function pluck(arr, propertyName){
return arr.map(getItem(propertyName));
}
var allTemperatures = pluck(data, 'temperatures');
var data = [
{
name: "Jamestown",
population: 2047,
temperatures: [-34, 67, 101, 87]
},
{
name: "Awesome Town",
population: 3568,
temperatures: [-3, 4, 9, 12]
},
{
name: "Funky Town",
population: 1000000,
temperatures: [75, 75, 75, 75, 75]
}
];
Functionnal way : combiner nos données
var populations = pluck(data, 'population'); // [2047, 3568, 1000000]
var averageTemps = pluck(data, 'temperatures').map(averageForArray); // [55.25, 5.5, 75]
Functionnal way : combiner nos données
var populations = pluck(data, 'population'); // [2047, 3568, 1000000]
var averageTemps = pluck(data, 'temperatures').map(averageForArray); // [55.25, 5.5, 75]
function combineArrays(arr1, arr2, resultArr){
resultArr = resultArr || [];
if(arr1.length === 0 || arr2.length === 0){
return resultArr;
} else {
return combineArrays(arr1.slice(1), arr2.slice(1), resultArr.push([arr1[0], arr2[0]]));
}
}
var chartData = combineArrays(averageTemps, populations);
Functionnal way
function formatChart(data){
return combineArrays(pluck(data, 'temperatures').map(averageForArray), pluck(data, 'population'));
}
Functionnal way
function formatChart(data){
return combineArrays(pluck(data, 'temperatures').map(averageForArray), pluck(data, 'population'));
}
Vs
function formatChart(data){
var coords = [],
totalTemp = 0,
averageTemp = 0;
for(var i=0; i < data.length; i++){
totalTemp = 0;
for(var j=0; j < data[i].temperatures.length; j++){
totalTemp += data[i].temperatures[j];
}
averageTemp = totalTemp / data[i].temperatures.length;
coords.push([averageTemp, data[i].population]);
}
return coords;
}
Functionnal way
function formatChart(data){
return _.zip(_.pluck(data, 'temperatures').map(t => _.sum(t) / t.length), _.pluck(data, 'population'));
}
Options
Quel est le problème ?
function getName(user){
return user.name;
}
Quel est le problème ?
function getName(user){
return user.name;
}
getName(); // ERROR: Cannot read property 'name' of undefined
Quel est le problème ?
function getName(user){
return user.name;
}
getName(); // ERROR: Cannot read property 'name' of undefined
getName(localStorage.getItem('user')); // ERROR ???
Option type
Option[A]
NoneSome[A]
Option (scala)
def getName(user: User): String {
return user.name
}
def getName(userOpt: Option[User]): String {
return userOpt.map(user => user.name).getOrElse("")
}
WTF !
Option.map() ??? List.map()
Monads
Monads
On en a déjà vu 2 :
● List[A] / Array[A]
● Option[A]
Monads
● Wrapper (context) M[A]
● Fonction map def map[A, B](f: A => B): M[A] => M[B]
● Fonction flatMap def flatMap[A, B](f: A => M[B]): M[A] => M[B]
Monads
● List
● Option
● Future
● Try
● Either
● ...
Conclusion
● passer toutes les données nécessaires en paramètre
● ne pas les modifier
● ne pas utiliser null, les exceptions, les boucles
● utiliser le moins possible les if
● faire des fonctions très simples et les composer
● utiliser des fonctions d’ordre supérieur
The One
“La programmation fonctionnelle permet de coder de manière plus modulaire
et plus productive, avec moins de code et moins de bugs”
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript

More Related Content

What's hot

The redux saga begins
The redux saga beginsThe redux saga begins
The redux saga begins
Daniel Franz
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)riue
 
Planet-HTML5-Game-Engine Javascript Performance Enhancement
Planet-HTML5-Game-Engine Javascript Performance EnhancementPlanet-HTML5-Game-Engine Javascript Performance Enhancement
Planet-HTML5-Game-Engine Javascript Performance Enhancement
up2soul
 
미려한 UI/UX를 위한 여정
미려한 UI/UX를 위한 여정미려한 UI/UX를 위한 여정
미려한 UI/UX를 위한 여정
SeungChul Kang
 
Let the type system be your friend
Let the type system be your friendLet the type system be your friend
Let the type system be your friend
The Software House
 
Kotlin collections
Kotlin collectionsKotlin collections
Kotlin collections
Myeongin Woo
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & Android
Jordi Gerona
 
Angular2 rxjs
Angular2 rxjsAngular2 rxjs
Angular2 rxjs
Christoffer Noring
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. Streams
DEVTYPE
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
scalaconfjp
 
JDD 2016 - Pawel Byszewski - Kotlin, why?
JDD 2016 - Pawel Byszewski - Kotlin, why?JDD 2016 - Pawel Byszewski - Kotlin, why?
JDD 2016 - Pawel Byszewski - Kotlin, why?
PROIDEA
 
Martin Fowler's Refactoring Techniques Quick Reference
Martin Fowler's Refactoring Techniques Quick ReferenceMartin Fowler's Refactoring Techniques Quick Reference
Martin Fowler's Refactoring Techniques Quick Reference
Seung-Bum Lee
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
Fabio Collini
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
Fabio Collini
 
Rxjs vienna
Rxjs viennaRxjs vienna
Rxjs vienna
Christoffer Noring
 
Compact and safely: static DSL on Kotlin
Compact and safely: static DSL on KotlinCompact and safely: static DSL on Kotlin
Compact and safely: static DSL on Kotlin
Dmitry Pranchuk
 
What are arrays in java script
What are arrays in java scriptWhat are arrays in java script
What are arrays in java script
Miguel Silva Loureiro
 
The core libraries you always wanted - Google Guava
The core libraries you always wanted - Google GuavaThe core libraries you always wanted - Google Guava
The core libraries you always wanted - Google Guava
Mite Mitreski
 

What's hot (20)

The redux saga begins
The redux saga beginsThe redux saga begins
The redux saga begins
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)
 
Planet-HTML5-Game-Engine Javascript Performance Enhancement
Planet-HTML5-Game-Engine Javascript Performance EnhancementPlanet-HTML5-Game-Engine Javascript Performance Enhancement
Planet-HTML5-Game-Engine Javascript Performance Enhancement
 
미려한 UI/UX를 위한 여정
미려한 UI/UX를 위한 여정미려한 UI/UX를 위한 여정
미려한 UI/UX를 위한 여정
 
Google Guava
Google GuavaGoogle Guava
Google Guava
 
Let the type system be your friend
Let the type system be your friendLet the type system be your friend
Let the type system be your friend
 
Kotlin collections
Kotlin collectionsKotlin collections
Kotlin collections
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & Android
 
Angular2 rxjs
Angular2 rxjsAngular2 rxjs
Angular2 rxjs
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. Streams
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
JDD 2016 - Pawel Byszewski - Kotlin, why?
JDD 2016 - Pawel Byszewski - Kotlin, why?JDD 2016 - Pawel Byszewski - Kotlin, why?
JDD 2016 - Pawel Byszewski - Kotlin, why?
 
Martin Fowler's Refactoring Techniques Quick Reference
Martin Fowler's Refactoring Techniques Quick ReferenceMartin Fowler's Refactoring Techniques Quick Reference
Martin Fowler's Refactoring Techniques Quick Reference
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
 
Rxjs vienna
Rxjs viennaRxjs vienna
Rxjs vienna
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Compact and safely: static DSL on Kotlin
Compact and safely: static DSL on KotlinCompact and safely: static DSL on Kotlin
Compact and safely: static DSL on Kotlin
 
What are arrays in java script
What are arrays in java scriptWhat are arrays in java script
What are arrays in java script
 
The core libraries you always wanted - Google Guava
The core libraries you always wanted - Google GuavaThe core libraries you always wanted - Google Guava
The core libraries you always wanted - Google Guava
 

Viewers also liked

Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Loïc Knuchel
 
Pasar grosir di jakarta
Pasar grosir di jakartaPasar grosir di jakarta
Pasar grosir di jakartahenigusnia
 
Lessons from Psalm 4
Lessons from Psalm 4Lessons from Psalm 4
Lessons from Psalm 4
HaynesStreet
 
Media evalution final versions
Media evalution final versionsMedia evalution final versions
Media evalution final versionshaydnbarry
 
Don't Forget Who You Are
Don't Forget Who You AreDon't Forget Who You Are
Don't Forget Who You AreHaynesStreet
 
Presentation1
Presentation1Presentation1
Presentation1cathz1024
 
BreeCS Example Report - Local Deliveries Catchment Tier Lifespan
BreeCS Example Report - Local Deliveries Catchment Tier LifespanBreeCS Example Report - Local Deliveries Catchment Tier Lifespan
BreeCS Example Report - Local Deliveries Catchment Tier Lifespan
Daniel Raines Communications / BreeCS Software
 
Ciprofloxacin 500 mg
Ciprofloxacin 500 mgCiprofloxacin 500 mg
Ciprofloxacin 500 mg
Herman Pasir
 
формування поняття відсотка 5 кл.
формування поняття відсотка 5 кл.формування поняття відсотка 5 кл.
формування поняття відсотка 5 кл.
Viktoria Mikolaenko
 
6 ways to save your hearing
6 ways to save your hearing6 ways to save your hearing
6 ways to save your hearing
Maico Audiological Services
 
Ida e Volta (Cover Alfonso Rubio Rodríguez)
Ida e Volta (Cover Alfonso Rubio Rodríguez)Ida e Volta (Cover Alfonso Rubio Rodríguez)
Ida e Volta (Cover Alfonso Rubio Rodríguez)
Alfonso Rubio Rodríguez
 
10 Things Calvin and Hobbes explained better than anyone else
10 Things Calvin and Hobbes explained better than anyone else 10 Things Calvin and Hobbes explained better than anyone else
10 Things Calvin and Hobbes explained better than anyone else
SlydS - Presentation Design & Training Studio
 
Automobile Rollaway: Is Your Car An Accident Waiting to Happen?
Automobile Rollaway:  Is Your Car An Accident Waiting to Happen?Automobile Rollaway:  Is Your Car An Accident Waiting to Happen?
Automobile Rollaway: Is Your Car An Accident Waiting to Happen?
Cost U Less Direct
 
Neuroscience and mobile app desing
Neuroscience and mobile app desingNeuroscience and mobile app desing
Neuroscience and mobile app desingMarketing4eCommerce
 
PAN Studio - Experience Design
PAN Studio - Experience DesignPAN Studio - Experience Design
PAN Studio - Experience DesignPANstudio
 

Viewers also liked (20)

Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
 
La programmation fonctionnelle en javascript / PF
La programmation fonctionnelle en javascript / PFLa programmation fonctionnelle en javascript / PF
La programmation fonctionnelle en javascript / PF
 
Pasar grosir di jakarta
Pasar grosir di jakartaPasar grosir di jakarta
Pasar grosir di jakarta
 
Lessons from Psalm 4
Lessons from Psalm 4Lessons from Psalm 4
Lessons from Psalm 4
 
Media evalution final versions
Media evalution final versionsMedia evalution final versions
Media evalution final versions
 
Don't Forget Who You Are
Don't Forget Who You AreDon't Forget Who You Are
Don't Forget Who You Are
 
Presentation1
Presentation1Presentation1
Presentation1
 
BreeCS Example Report - Local Deliveries Catchment Tier Lifespan
BreeCS Example Report - Local Deliveries Catchment Tier LifespanBreeCS Example Report - Local Deliveries Catchment Tier Lifespan
BreeCS Example Report - Local Deliveries Catchment Tier Lifespan
 
Ciprofloxacin 500 mg
Ciprofloxacin 500 mgCiprofloxacin 500 mg
Ciprofloxacin 500 mg
 
формування поняття відсотка 5 кл.
формування поняття відсотка 5 кл.формування поняття відсотка 5 кл.
формування поняття відсотка 5 кл.
 
6 ways to save your hearing
6 ways to save your hearing6 ways to save your hearing
6 ways to save your hearing
 
Deloitte tmt-predictions-2014
Deloitte tmt-predictions-2014Deloitte tmt-predictions-2014
Deloitte tmt-predictions-2014
 
Ida e Volta (Cover Alfonso Rubio Rodríguez)
Ida e Volta (Cover Alfonso Rubio Rodríguez)Ida e Volta (Cover Alfonso Rubio Rodríguez)
Ida e Volta (Cover Alfonso Rubio Rodríguez)
 
Star 22 26 32
Star 22 26 32Star 22 26 32
Star 22 26 32
 
10 Things Calvin and Hobbes explained better than anyone else
10 Things Calvin and Hobbes explained better than anyone else 10 Things Calvin and Hobbes explained better than anyone else
10 Things Calvin and Hobbes explained better than anyone else
 
Automobile Rollaway: Is Your Car An Accident Waiting to Happen?
Automobile Rollaway:  Is Your Car An Accident Waiting to Happen?Automobile Rollaway:  Is Your Car An Accident Waiting to Happen?
Automobile Rollaway: Is Your Car An Accident Waiting to Happen?
 
cara grosir pakaian
cara grosir pakaiancara grosir pakaian
cara grosir pakaian
 
Neuroscience and mobile app desing
Neuroscience and mobile app desingNeuroscience and mobile app desing
Neuroscience and mobile app desing
 
PAN Studio - Experience Design
PAN Studio - Experience DesignPAN Studio - Experience Design
PAN Studio - Experience Design
 
Influencers Copy
Influencers CopyInfluencers Copy
Influencers Copy
 

Similar to Programmation fonctionnelle en JavaScript

You will learn RxJS in 2017
You will learn RxJS in 2017You will learn RxJS in 2017
You will learn RxJS in 2017
名辰 洪
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
Nick Lee
 
Building Evented Single Page Applications
Building Evented Single Page ApplicationsBuilding Evented Single Page Applications
Building Evented Single Page Applications
Steve Smith
 
Building evented single page applications
Building evented single page applicationsBuilding evented single page applications
Building evented single page applications
Steve Smith
 
Fact, Fiction, and FP
Fact, Fiction, and FPFact, Fiction, and FP
Fact, Fiction, and FP
Brian Lonsdorf
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
Rebecca Murphey
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montageKris Kowal
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Treeadamlogic
 
React table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterReact table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilter
Katy Slemon
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
Astrails
 
Building Smart Async Functions For Mobile
Building Smart Async Functions For MobileBuilding Smart Async Functions For Mobile
Building Smart Async Functions For MobileGlan Thomas
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
Bruno Scopelliti
 
Gearmam, from the_worker's_perspective copy
Gearmam, from the_worker's_perspective copyGearmam, from the_worker's_perspective copy
Gearmam, from the_worker's_perspective copyBrian Aker
 
Gearmam, from the_worker's_perspective copy
Gearmam, from the_worker's_perspective copyGearmam, from the_worker's_perspective copy
Gearmam, from the_worker's_perspective copyBrian Aker
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
Rafael Felix da Silva
 
React Native - Workshop
React Native - WorkshopReact Native - Workshop
React Native - Workshop
Fellipe Chagas
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说Ting Lv
 

Similar to Programmation fonctionnelle en JavaScript (20)

You will learn RxJS in 2017
You will learn RxJS in 2017You will learn RxJS in 2017
You will learn RxJS in 2017
 
Pengenalan blaast platform sdk
Pengenalan blaast platform sdkPengenalan blaast platform sdk
Pengenalan blaast platform sdk
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
Building Evented Single Page Applications
Building Evented Single Page ApplicationsBuilding Evented Single Page Applications
Building Evented Single Page Applications
 
Building evented single page applications
Building evented single page applicationsBuilding evented single page applications
Building evented single page applications
 
Fact, Fiction, and FP
Fact, Fiction, and FPFact, Fiction, and FP
Fact, Fiction, and FP
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montage
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Tree
 
React table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterReact table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilter
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
 
Building Smart Async Functions For Mobile
Building Smart Async Functions For MobileBuilding Smart Async Functions For Mobile
Building Smart Async Functions For Mobile
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 
Gearmam, from the_worker's_perspective copy
Gearmam, from the_worker's_perspective copyGearmam, from the_worker's_perspective copy
Gearmam, from the_worker's_perspective copy
 
Gearmam, from the_worker's_perspective copy
Gearmam, from the_worker's_perspective copyGearmam, from the_worker's_perspective copy
Gearmam, from the_worker's_perspective copy
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
React Native - Workshop
React Native - WorkshopReact Native - Workshop
React Native - Workshop
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说
 
Codigo taller-plugins
Codigo taller-pluginsCodigo taller-plugins
Codigo taller-plugins
 

More from Loïc Knuchel

Scala bad practices, scala.io 2019
Scala bad practices, scala.io 2019Scala bad practices, scala.io 2019
Scala bad practices, scala.io 2019
Loïc Knuchel
 
Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDe...
Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDe...Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDe...
Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDe...
Loïc Knuchel
 
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Loïc Knuchel
 
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
Loïc Knuchel
 
FP is coming... le 19/05/2016
FP is coming... le 19/05/2016FP is coming... le 19/05/2016
FP is coming... le 19/05/2016
Loïc Knuchel
 
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
Loïc Knuchel
 
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
Loïc Knuchel
 
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Loïc Knuchel
 
Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015
Loïc Knuchel
 
Devoxx 2015, ionic chat
Devoxx 2015, ionic chatDevoxx 2015, ionic chat
Devoxx 2015, ionic chatLoïc Knuchel
 
Ionic HumanTalks - 11/03/2015
Ionic HumanTalks - 11/03/2015Ionic HumanTalks - 11/03/2015
Ionic HumanTalks - 11/03/2015
Loïc Knuchel
 
Ionic bbl le 19 février 2015
Ionic bbl le 19 février 2015Ionic bbl le 19 février 2015
Ionic bbl le 19 février 2015
Loïc Knuchel
 
Des maths et des recommandations - Devoxx 2014
Des maths et des recommandations - Devoxx 2014Des maths et des recommandations - Devoxx 2014
Des maths et des recommandations - Devoxx 2014Loïc Knuchel
 

More from Loïc Knuchel (13)

Scala bad practices, scala.io 2019
Scala bad practices, scala.io 2019Scala bad practices, scala.io 2019
Scala bad practices, scala.io 2019
 
Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDe...
Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDe...Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDe...
Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDe...
 
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
 
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
 
FP is coming... le 19/05/2016
FP is coming... le 19/05/2016FP is coming... le 19/05/2016
FP is coming... le 19/05/2016
 
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
 
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
 
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
 
Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015
 
Devoxx 2015, ionic chat
Devoxx 2015, ionic chatDevoxx 2015, ionic chat
Devoxx 2015, ionic chat
 
Ionic HumanTalks - 11/03/2015
Ionic HumanTalks - 11/03/2015Ionic HumanTalks - 11/03/2015
Ionic HumanTalks - 11/03/2015
 
Ionic bbl le 19 février 2015
Ionic bbl le 19 février 2015Ionic bbl le 19 février 2015
Ionic bbl le 19 février 2015
 
Des maths et des recommandations - Devoxx 2014
Des maths et des recommandations - Devoxx 2014Des maths et des recommandations - Devoxx 2014
Des maths et des recommandations - Devoxx 2014
 

Recently uploaded

Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
Matt Welsh
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 

Recently uploaded (20)

Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 

Programmation fonctionnelle en JavaScript

  • 2. The Obvious “La programmation fonctionnelle est une manière de programmer principalement basée sur des fonctions”
  • 3. The Headache “La programmation fonctionnelle est un style de développement qui promeut les fonctions indépendantes de l’état du programme.”
  • 4. The One “La programmation fonctionnelle permet de coder de manière plus modulaire et plus productive, avec moins de code et moins de bugs”
  • 6. Transformer un tableau var names = ['Finn', 'Rey', 'Poe', 'Kaylo']; function upperCaseArray(arr){ var ret = []; for(var i=0; i<arr.length; i++){ ret[i] = arr[i].toUpperCase(); } return ret; } console.log(upperCaseArray(names)); // ['FINN', 'REY', 'POE', 'KAYLO']
  • 7. Transformer un tableau var names = ['Finn', 'Rey', 'Poe', 'Kaylo']; function upperCaseArray(arr){ var ret = []; for(var i=0; i<arr.length; i++){ ret[i] = arr[i].toUpperCase(); } return ret; } console.log(upperCaseArray(names)); // ['FINN', 'REY', 'POE', 'KAYLO'] function upperCaseArray(arr){ return arr.map(function(item){ return item.toUpperCase(); }); }
  • 8. Créer son .map() Array.prototype.map = function(callback){ var array = this; var result = []; for(var i=0; i<array.length; i++){ result[i] = callback(array[i]); } return result; };
  • 10. Traiter des données complexes var claims = [{ wan: '123', actions: [ {name: 'sendPicture', pictures: [ {path: '123/1.jpg', deleted: true, sync: false}, {path: '123/2.jpg', deleted: false, sync: true}, ]}, {name: 'changeStep', step: 'COM'}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: false, sync: true}, {path: '123/4.jpg', deleted: false, sync: true} ]}, {name: 'sendPicture', pictures: [ {path: '123/5.jpg', deleted: true, sync: false}, {path: '123/6.jpg', deleted: false, sync: false} ]} ] }, { wan: '456', actions: [ {name: 'sendPicture', pictures: [ {path: '456/1.jpg', deleted: false, sync: true}, {path: '456/2.jpg', deleted: false, sync: true}, ]}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: true, sync: false}, {path: '123/4.jpg', deleted: true, sync: false} ]} ] }];
  • 11. Traiter des données complexes var claims = [{ wan: '123', actions: [ {name: 'sendPicture', pictures: [ {path: '123/1.jpg', deleted: true, sync: false}, {path: '123/2.jpg', deleted: false, sync: true}, ]}, {name: 'changeStep', step: 'COM'}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: false, sync: true}, {path: '123/4.jpg', deleted: false, sync: true} ]}, {name: 'sendPicture', pictures: [ {path: '123/5.jpg', deleted: true, sync: false}, {path: '123/6.jpg', deleted: false, sync: false} ]} ] }, { wan: '456', actions: [ {name: 'sendPicture', pictures: [ {path: '456/1.jpg', deleted: false, sync: true}, {path: '456/2.jpg', deleted: false, sync: true}, ]}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: true, sync: false}, {path: '123/4.jpg', deleted: true, sync: false} ]} ] }]; function doSomething(claims){ var pictures = []; for(var i=0; i<claims.length; i++){ var claim = claims[i]; for(var j=0; j<claim.actions.length; j++){ var action = claim.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted && !picture.sync){ pictures.push(picture); } } } } } return pictures; }
  • 12. Traiter des données complexes var claims = [{ wan: '123', actions: [ {name: 'sendPicture', pictures: [ {path: '123/1.jpg', deleted: true, sync: false}, {path: '123/2.jpg', deleted: false, sync: true}, ]}, {name: 'changeStep', step: 'COM'}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: false, sync: true}, {path: '123/4.jpg', deleted: false, sync: true} ]}, {name: 'sendPicture', pictures: [ {path: '123/5.jpg', deleted: true, sync: false}, {path: '123/6.jpg', deleted: false, sync: false} ]} ] }, { wan: '456', actions: [ {name: 'sendPicture', pictures: [ {path: '456/1.jpg', deleted: false, sync: true}, {path: '456/2.jpg', deleted: false, sync: true}, ]}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: true, sync: false}, {path: '123/4.jpg', deleted: true, sync: false} ]} ] }]; function doSomething(claims){ var pictures = []; for(var i=0; i<claims.length; i++){ var claim = claims[i]; for(var j=0; j<claim.actions.length; j++){ var action = claim.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted && !picture.sync){ pictures.push(picture); } } } } } return pictures; }
  • 13. Traiter des données complexes (lodash) function getPicturesToSync(claims){ var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; })); var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function (action){ return action.pictures; })); return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;}); }
  • 14. Traiter des données complexes (lodash) function getPicturesToSync(claims){ var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; })); var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function (action){ return action.pictures; })); return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;}); } _.map(array, callback) crée un tableau avec les valeurs retournées par le callback en paramètre.
  • 15. Traiter des données complexes (lodash) function getPicturesToSync(claims){ var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; })); var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function (action){ return action.pictures; })); return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;}); } _.flatten(array) crée un tableau simple à partir d’un tableau de tableaux.
  • 16. Traiter des données complexes (lodash) function getPicturesToSync(claims){ var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; })); var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function (action){ return action.pictures; })); return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;}); } _.filter(array, callback) crée un tableau en gardant que les éléments pour lesquels le callback renvoi true.
  • 17. Traiter des données complexes (lodash) function getPicturesToSync(claims){ var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; })); var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function (action){ return action.pictures; })); return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;}); }
  • 18. Traiter des données complexes (lodash) function getPicturesToSync(claims){ var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; })); var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function (action){ return action.pictures; })); return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;}); }
  • 19. Traiter des données complexes (lodash) function getPicturesToSync(claims){ var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; })); var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function (action){ return action.pictures; })); return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;}); }
  • 20. Traiter des données complexes (lodash) function getPicturesToSync(claims){ var actions = _.flatten(_.map(claims, function(claim){ return claim.actions; })); var pictures = _.flatten(_.map(_.filter(actions, function(action){ return action.name === 'sendPicture'; }), function (action){ return action.pictures; })); return _.filter(pictures, function(picture){ return picture.deleted === false && picture.sync === false;}); }
  • 21. Améliorer les tableaux JavaScript Array.prototype.find = function(callback){ return _.find(this, callback); } Array.prototype.filter = function(callback){ return _.filter(this, callback); } Array.prototype.map = function(callback){ return _.map(this, callback); } Array.prototype.flatten = function() { return _.flatten(this); }
  • 22. Traiter des données complexes (js array) function getPicturesToSync(claims){ return claims .map(function(claim){ return claim.actions; }) .flatten() .filter(function(action){ return action.name === 'sendPicture'; }) .map(function(action){ return action.pictures; }) .flatten() .filter(function(picture){ return picture.deleted === false && picture.sync === false;}); }
  • 23. Traiter des données complexes (es6 fat arrow) function getPicturesToSync(claims){ return claims .map(claim => claim.actions) .flatten() .filter(action => action.name === 'sendPicture') .map(action => action.pictures) .flatten() .filter(picture => picture.deleted === false && picture.sync === false); }
  • 24. Traiter des données complexes (pluck) function getPicturesToSync(claims){ return claims .map('actions') .flatten() .filter({name: 'sendPicture'}) .map('pictures') .flatten() .filter({deleted: false, sync: false}); }
  • 25. Traiter des données complexes (flatMap) var data = [ {id: '1', values: [1, 2, 3]}, {id: '2', values: [4, 5]}, ]; data.map('values'); // [[1, 2, 3], [4, 5]] data.map('values').flatten(); // [1, 2, 3, 4, 5]
  • 26. Traiter des données complexes (flatMap) Array.prototype.flatMap = function(callback){ return _.flatten(_.map(this, callback)); } var data = [ {id: '1', values: [1, 2, 3]}, {id: '2', values: [4, 5]}, ]; data.map('values'); // [[1, 2, 3], [4, 5]] data.map('values').flatten(); // [1, 2, 3, 4, 5] data.flatMap('values'); // [1, 2, 3, 4, 5]
  • 27. Traiter des données complexes (flatMap) function getPicturesToSync(claims){ return claims .flatMap('actions') .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false, sync: false}); }
  • 28. function getPicturesToSync(claims){ return claims .flatMap('actions') .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false, sync: false}); } Bilan function getPicturesToSync(claims){ var pictures = []; for(var i=0; i<claims.length; i++){ var claim = claims[i]; for(var j=0; j<claim.actions.length; j++){ var action = claim.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted && !picture.sync){ pictures.push(picture); } } } } } return pictures; }
  • 29. function getPicturesToSync(claims){ return claims .flatMap('actions') .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false, sync: false}); } ● moins de code ● moins de bugs ● plus de productivité Bilan function getPicturesToSync(claims){ var pictures = []; for(var i=0; i<claims.length; i++){ var claim = claims[i]; for(var j=0; j<claim.actions.length; j++){ var action = claim.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted && !picture.sync){ pictures.push(picture); } } } } } return pictures; }
  • 30.
  • 31. Autre exemple var claims = [{ wan: '123', actions: [ {name: 'sendPicture', pictures: [ {path: '123/1.jpg', deleted: true, sync: false}, {path: '123/2.jpg', deleted: false, sync: true}, ]}, {name: 'changeStep', step: 'COM'}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: false, sync: true}, {path: '123/4.jpg', deleted: false, sync: true} ]}, {name: 'sendPicture', pictures: [ {path: '123/5.jpg', deleted: true, sync: false}, {path: '123/6.jpg', deleted: false, sync: false} ]} ] }, { wan: '456', actions: [ {name: 'sendPicture', pictures: [ {path: '456/1.jpg', deleted: false, sync: true}, {path: '456/2.jpg', deleted: false, sync: true}, ]}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: true, sync: false}, {path: '123/4.jpg', deleted: true, sync: false} ]} ] }]; function doSomething(claims, wan){ return claims .find({wan: wan}).actions .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false}); }
  • 32. Autre exemple var claims = [{ wan: '123', actions: [ {name: 'sendPicture', pictures: [ {path: '123/1.jpg', deleted: true, sync: false}, {path: '123/2.jpg', deleted: false, sync: true}, ]}, {name: 'changeStep', step: 'COM'}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: false, sync: true}, {path: '123/4.jpg', deleted: false, sync: true} ]}, {name: 'sendPicture', pictures: [ {path: '123/5.jpg', deleted: true, sync: false}, {path: '123/6.jpg', deleted: false, sync: false} ]} ] }, { wan: '456', actions: [ {name: 'sendPicture', pictures: [ {path: '456/1.jpg', deleted: false, sync: true}, {path: '456/2.jpg', deleted: false, sync: true}, ]}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: true, sync: false}, {path: '123/4.jpg', deleted: true, sync: false} ]} ] }]; function doSomething(claims, wan){ return claims .find({wan: wan}).actions .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false}); }
  • 33. Bilan function getPictures(claims, wan){ for(var i=0; i<claims.length; i++){ var claim = claims[i]; if(claim.wan === wan){ var pictures = []; for(var j=0; j<=claim.actions.length; j++){ var action = claim.actions[i]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(picture.deleted){ pictures.push(picture); } } } } return pictures; } } } function getPictures(claims, wan){ return claims .find({wan: wan}).actions .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false}); }
  • 34. Bilan function getPictures(claims, wan){ for(var i=0; i<claims.length; i++){ var claim = claims[i]; if(claim.wan === wan){ var pictures = []; for(var j=0; j<=claim.actions.length; j++){ var action = claim.actions[i]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(picture.deleted){ pictures.push(picture); } } } } return pictures; } } } function getPictures(claims, wan){ return claims .find({wan: wan}).actions .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false}); }
  • 35. Bilan (correct) function getPictures(claims, wan){ for(var i=0; i<claims.length; i++){ var claim = claims[i]; if(claim.wan === wan){ var pictures = []; for(var j=0; j<claim.actions.length; j++){ var action = claim.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted){ pictures.push(picture); } } } } return pictures; } } } function getPictures(claims, wan){ return claims .find({wan: wan}).actions .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false}); }
  • 36. Bilan La programmation fonctionnelle permet de déclarer des intentions. function getPictures(claims, wan){ return claims .find({wan: wan}).actions .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false}); } function getPicturesToSync(claims){ return claims .flatMap('actions') .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false, sync: false}); }
  • 37. Bilan La programmation fonctionnelle permet de déclarer des intentions. Au final, on ne sait pas vraiment ce qui est fait et quand. function getPictures(claims, wan){ return claims .find({wan: wan}).actions .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false}); } function getPicturesToSync(claims){ return claims .flatMap('actions') .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false, sync: false}); }
  • 38. Bilan La programmation fonctionnelle permet de déclarer des intentions. Au final, on ne sait pas vraiment ce qui est fait et quand. Ce qui permet de changer le fonctionnement du programme sans changer le code. function getPictures(claims, wan){ return claims .find({wan: wan}).actions .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false}); } function getPicturesToSync(claims){ return claims .flatMap('actions') .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false, sync: false}); }
  • 39. Bilan La programmation fonctionnelle permet de déclarer des intentions. Au final, on ne sait pas vraiment ce qui est fait et quand. Ce qui permet de changer le fonctionnement du programme sans changer le code. Ex: ● synchrone => asynchrone ● impératif => lazy (cf Lazy.js) function getPictures(claims, wan){ return claims .find({wan: wan}).actions .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false}); } function getPicturesToSync(claims){ return claims .flatMap('actions') .filter({name: 'sendPicture'}) .flatMap('pictures') .filter({deleted: false, sync: false}); }
  • 40. Quelques autres fonctions de lodash ● groupBy _.groupBy(claims[0].actions, function(action){ return action.name; }); /* Result : { 'sendPicture': [ {name: 'sendPicture', pictures: [...]}, {name: 'sendPicture', pictures: [...]}, {name: 'sendPicture', pictures: [...]} ], 'changeStep': [ {name: 'changeStep', step: 'COM'} ] } */
  • 41. Quelques autres fonctions de lodash ● groupBy ● partition _.partition([1, 2, 3], function(n){ return n % 2; }); // Result : [[1, 3], [2]]
  • 42. Quelques autres fonctions de lodash ● groupBy ● partition ● sortBy _.sortBy([2, 3, 1], function(n){ return n; }); // Result : [1, 2, 3]
  • 43. Quelques autres fonctions de lodash ● groupBy ● partition ● sortBy ● take / drop _.take([1, 2, 3, 4, 5], 3); // Result : [1, 2, 3] _.drop([1, 2, 3, 4, 5], 1); // Result : [2, 3, 4, 5]
  • 44. Quelques autres fonctions de lodash ● groupBy ● partition ● sortBy ● take / drop ● uniq _.uniq(['foo', 'bar', 'foo', 'foo']); // Result : ['foo', 'bar'] _.uniq([{wan: '1'}, {wan: '2'}, {wan: '1'}], 'wan'); // Result : [{wan: '1'}, {wan: '2'}]
  • 45. Quelques autres fonctions de lodash ● groupBy ● partition ● sortBy ● take / drop ● uniq ● reduce _.reduce(claims, function(count, claim){ return count + claim.actions.length; }, 0); // Result: 6
  • 46. Quelques autres fonctions de lodash ● groupBy ● partition ● sortBy ● take / drop ● uniq ● reduce ● sum / min / max _.sum(['Finn', 'Rey', 'Poe', 'Kaylo'], function(name){ return name.length; }); // Result : 15
  • 47. Quelques autres fonctions de lodash ● groupBy ● partition ● sortBy ● take / drop ● uniq ● reduce ● sum / min / max ● ...
  • 49. No side effect Effets de bord: lancer une exception/erreur, faire un appel (bdd, http, fichier…), récupérer la date actuelle, modifier un paramètre, accéder à une variable “globale”, mettre un log
  • 52. Bénéfices ● Moins de code (~÷3 par rapport à Java) ● Plus compréhensible ● Plus facile à réutiliser / composer ● Plus facile à tester ● Moins de bugs
  • 53. Exemple: Afficher ces données dans un graph var data = [ { name: "Jamestown", population: 2047, temperatures: [-34, 67, 101, 87] }, { name: "Awesome Town", population: 3568, temperatures: [-3, 4, 9, 12] }, { name: "Funky Town", population: 1000000, temperatures: [75, 75, 75, 75, 75] } ]; // Result : [ [55.25, 2047], // [average temperature, population] [5.5, 3568], [75, 1000000] ]
  • 54. Code impératif function formatChart(data){ var coords = [], totalTemp = 0, averageTemp = 0; for(var i=0; i < data.length; i++){ totalTemp = 0; for(var j=0; j < data[i].temperatures.length; j++){ totalTemp += data[i].temperatures[j]; } averageTemp = totalTemp / data[i].temperatures.length; coords.push([averageTemp, data[i].population]); } return coords; }
  • 55. Code impératif function formatChart(data){ var coords = [], totalTemp = 0, averageTemp = 0; for(var i=0; i < data.length; i++){ totalTemp = 0; for(var j=0; j < data[i].temperatures.length; j++){ totalTemp += data[i].temperatures[j]; } averageTemp = totalTemp / data[i].temperatures.length; coords.push([averageTemp, data[i].population]); } return coords; } ● Pas réutilisable ● Difficile à comprendre ● bugs probables
  • 56. Functionnal way : sommer les températures var totalTemp = totalForArray(0, temperatures); // recursive to avoid loop function totalForArray(currentTotal, arr){ if(arr.length === 0){ return currentTotal; } else { return totalForArray(currentTotal + arr[0], arr.slice(1)); } }
  • 57. Functionnal way : sommer les températures var totalTemp = totalForArray(0, temperatures); // recursive to avoid loop function totalForArray(currentTotal, arr){ if(arr.length === 0){ return currentTotal; } else { return totalForArray(currentTotal + arr[0], arr.slice(1)); } } Vs function totalForArray(currentTotal, arr){ return arr.reduce((total, item) => total + item, currentTotal); }
  • 58. Functionnal way : calculer la température moyenne function average(total, count){ return total / count; }
  • 59. Functionnal way : calculer la température moyenne function average(total, count){ return total / count; } function averageForArray(arr){ return average(totalForArray(0, arr), arr.length); }
  • 60. Functionnal way : calculer la température moyenne function average(total, count){ return total / count; } function averageForArray(arr){ return average(totalForArray(0, arr), arr.length); } var averageTemp = averageForArray(temperatures);
  • 61. Functionnal way : récupérer les températures var allTemperatures = data.map(function(item){ return item.temperatures; }); var data = [ { name: "Jamestown", population: 2047, temperatures: [-34, 67, 101, 87] }, { name: "Awesome Town", population: 3568, temperatures: [-3, 4, 9, 12] }, { name: "Funky Town", population: 1000000, temperatures: [75, 75, 75, 75, 75] } ];
  • 62. Functionnal way : récupérer les températures var allTemperatures = data.map(function(item){ return item.temperatures; }); // simplify & shorten map syntax function getItem(propertyName){ return function(item){ return item[propertyName]; } } var allTemperatures = data.map(getItem('temperature')); var data = [ { name: "Jamestown", population: 2047, temperatures: [-34, 67, 101, 87] }, { name: "Awesome Town", population: 3568, temperatures: [-3, 4, 9, 12] }, { name: "Funky Town", population: 1000000, temperatures: [75, 75, 75, 75, 75] } ];
  • 63. Curryfication function add1(b){ return 1+b; } console.log(add1(2)); // 3 function addCurry(a){ return function(b){ return a+b; } } var add1 = addCurry(1); var add2 = addCurry(2); console.log(add1(2)); // 3 console.log(add2(2)); // 4
  • 64. Functionnal way : récupérer les températures var allTemperatures = data.map(function(item){ return item.temperatures; }); // simplify & shorten map syntax function getItem(propertyName){ return function(item){ return item[propertyName]; } } var allTemperatures = data.map(getItem('temperature')); var data = [ { name: "Jamestown", population: 2047, temperatures: [-34, 67, 101, 87] }, { name: "Awesome Town", population: 3568, temperatures: [-3, 4, 9, 12] }, { name: "Funky Town", population: 1000000, temperatures: [75, 75, 75, 75, 75] } ];
  • 65. Functionnal way : récupérer les températures var allTemperatures = data.map(function(item){ return item.temperatures; }); // simplify & shorten map syntax function getItem(propertyName){ return function(item){ return item[propertyName]; } } var allTemperatures = data.map(getItem('temperature')); // more concise again ! function pluck(arr, propertyName){ return arr.map(getItem(propertyName)); } var allTemperatures = pluck(data, 'temperatures'); var data = [ { name: "Jamestown", population: 2047, temperatures: [-34, 67, 101, 87] }, { name: "Awesome Town", population: 3568, temperatures: [-3, 4, 9, 12] }, { name: "Funky Town", population: 1000000, temperatures: [75, 75, 75, 75, 75] } ];
  • 66. Functionnal way : combiner nos données var populations = pluck(data, 'population'); // [2047, 3568, 1000000] var averageTemps = pluck(data, 'temperatures').map(averageForArray); // [55.25, 5.5, 75]
  • 67. Functionnal way : combiner nos données var populations = pluck(data, 'population'); // [2047, 3568, 1000000] var averageTemps = pluck(data, 'temperatures').map(averageForArray); // [55.25, 5.5, 75] function combineArrays(arr1, arr2, resultArr){ resultArr = resultArr || []; if(arr1.length === 0 || arr2.length === 0){ return resultArr; } else { return combineArrays(arr1.slice(1), arr2.slice(1), resultArr.push([arr1[0], arr2[0]])); } } var chartData = combineArrays(averageTemps, populations);
  • 68. Functionnal way function formatChart(data){ return combineArrays(pluck(data, 'temperatures').map(averageForArray), pluck(data, 'population')); }
  • 69. Functionnal way function formatChart(data){ return combineArrays(pluck(data, 'temperatures').map(averageForArray), pluck(data, 'population')); } Vs function formatChart(data){ var coords = [], totalTemp = 0, averageTemp = 0; for(var i=0; i < data.length; i++){ totalTemp = 0; for(var j=0; j < data[i].temperatures.length; j++){ totalTemp += data[i].temperatures[j]; } averageTemp = totalTemp / data[i].temperatures.length; coords.push([averageTemp, data[i].population]); } return coords; }
  • 70. Functionnal way function formatChart(data){ return _.zip(_.pluck(data, 'temperatures').map(t => _.sum(t) / t.length), _.pluck(data, 'population')); }
  • 72. Quel est le problème ? function getName(user){ return user.name; }
  • 73. Quel est le problème ? function getName(user){ return user.name; } getName(); // ERROR: Cannot read property 'name' of undefined
  • 74. Quel est le problème ? function getName(user){ return user.name; } getName(); // ERROR: Cannot read property 'name' of undefined getName(localStorage.getItem('user')); // ERROR ???
  • 76. Option (scala) def getName(user: User): String { return user.name } def getName(userOpt: Option[User]): String { return userOpt.map(user => user.name).getOrElse("") }
  • 79.
  • 80.
  • 81. Monads On en a déjà vu 2 : ● List[A] / Array[A] ● Option[A]
  • 82. Monads ● Wrapper (context) M[A] ● Fonction map def map[A, B](f: A => B): M[A] => M[B] ● Fonction flatMap def flatMap[A, B](f: A => M[B]): M[A] => M[B]
  • 83. Monads ● List ● Option ● Future ● Try ● Either ● ...
  • 84. Conclusion ● passer toutes les données nécessaires en paramètre ● ne pas les modifier ● ne pas utiliser null, les exceptions, les boucles ● utiliser le moins possible les if ● faire des fonctions très simples et les composer ● utiliser des fonctions d’ordre supérieur
  • 85. The One “La programmation fonctionnelle permet de coder de manière plus modulaire et plus productive, avec moins de code et moins de bugs”