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
 
Google Guava
Google GuavaGoogle Guava
Google Guava
Alexander Korotkikh
 
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
 
Scala introduction
Scala introductionScala introduction
Scala introduction
Alf Kristian Støyle
 
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 versions
haydnbarry
 
Don't Forget Who You Are
Don't Forget Who You AreDon't Forget Who You Are
Don't Forget Who You Are
HaynesStreet
 
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
 
Deloitte tmt-predictions-2014
Deloitte tmt-predictions-2014Deloitte tmt-predictions-2014
Deloitte tmt-predictions-2014
Marketing4eCommerce
 
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
 
cara grosir pakaian
cara grosir pakaiancara grosir pakaian
cara grosir pakaian
www.grosirdress.com
 
Neuroscience and mobile app desing
Neuroscience and mobile app desingNeuroscience and mobile app desing
Neuroscience and mobile app desing
Marketing4eCommerce
 
PAN Studio - Experience Design
PAN Studio - Experience DesignPAN Studio - Experience Design
PAN Studio - Experience Design
PANstudio
 
Influencers Copy
Influencers CopyInfluencers Copy
Influencers Copy
Astrid Ramos
 

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
名辰 洪
 
Pengenalan blaast platform sdk
Pengenalan blaast platform sdkPengenalan blaast platform sdk
Pengenalan blaast platform sdk
Arief Bayu Purwanto
 
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
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
Chris Neale
 
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 montage
Kris 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 Tree
adamlogic
 
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 Mobile
Glan 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 copy
Brian 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 copy
Brian 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
 
Codigo taller-plugins
Codigo taller-pluginsCodigo taller-plugins
Codigo taller-plugins
Rocío Valdivia
 

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

一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理
dakas1
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
mz5nrf0n
 
Liberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptxLiberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptx
Massimo Artizzu
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
Karya Keeper
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
Bert Jan Schrijver
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
rodomar2
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
Sven Peters
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
Patrick Weigel
 
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
kalichargn70th171
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
safelyiotech
 
How to write a program in any programming language
How to write a program in any programming languageHow to write a program in any programming language
How to write a program in any programming language
Rakesh Kumar R
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
ShulagnaSarkar2
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
gapen1
 
YAML crash COURSE how to write yaml file for adding configuring details
YAML crash COURSE how to write yaml file for adding configuring detailsYAML crash COURSE how to write yaml file for adding configuring details
YAML crash COURSE how to write yaml file for adding configuring details
NishanthaBulumulla1
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
Peter Muessig
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
Remote DBA Services
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
Marcin Chrost
 

Recently uploaded (20)

一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
 
Liberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptxLiberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptx
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
 
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
The Key to Digital Success_ A Comprehensive Guide to Continuous Testing Integ...
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
 
How to write a program in any programming language
How to write a program in any programming languageHow to write a program in any programming language
How to write a program in any programming language
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
 
YAML crash COURSE how to write yaml file for adding configuring details
YAML crash COURSE how to write yaml file for adding configuring detailsYAML crash COURSE how to write yaml file for adding configuring details
YAML crash COURSE how to write yaml file for adding configuring details
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
 

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”