Faire de la programmation fonctionnelle en JavaScript avec Ramda

Cet article n'est pas de présenter ce qu'est de la programmation fonctionnelle (un bouquin pas mal sur le sujet). Le but est de plutôt présenter Ramda qui permet d'en faire simplement.



Prenons un code plutôt simple, où nous allons filtrer une liste d'utilisateur en se basant:
  • Sur son nom ('Buzz')
  • Si l'utilisateur est valide ou non

/**
 * Keep only valid @{User} with name 'Buzz'
 * @method
 * @param {User[]} users
 * @returns {User[]} Filtered list of @{User}
 */
function validUsersNamedBuzz(users) {
  var filtered = [];
  for (user of users) {
 if (user.name === 'Buzz' && _.isEmpty(user.errors)) {
    filtered.push(user);
 }
  }
  return filtered;
}


Maintenant regardons avec le classique et fameux Lodash, qui permet l'enchaînement et la composition de fonctions utilitaires, soit à nous, soit de Lodash.

/**
 * Keep only valid @{User} with name 'Buzz'
 * @method
 * @param {User[]} users
 * @returns {User[]} Filtered list of @{User}
 */
function validUsersNamedBuzz(users) {
  return _.filter(users, function(user) { 
 return user.name === 'Buzz' && _.isEmpty(user.errors); 
  });
}


Il existe une variante se basant sur la transduction (enchaînement implicite de méthodes):

/**
 * Keep only valid @{User} with name 'Buzz'
 * @method
 * @param {User[]} users
 * @returns {User[]} Filtered list of @{User}
 */
function validUsersNamedBuzz(users) {
  return _(users)
 .filter(function (user) {
  return user.name === 'Buzz';
 })
 .filter(function (user) {
  return _.isEmpty(user.errors);
 })
 .get();
}


Autrement, voici la version Ramda:

/**
 * Keep only valid @{User} with name 'Buzz'
 * @method
 * @param {User[]} users
 * @returns {User[]} Filtered list of @{User}
 */
var validUsersNamedBuzz = R.filter(R.where({ 'name': 'Buzz', 'errors': R.isEmpty }));



Pas mal non ? Ramda propose un grand nombre de fonctions utilitaires, dont la plupart sont composables et chainables comme l'exemple précédent. Car Ramda essaie de rendre "curryable" ses fonctions automatiquement.

Le principe du "currying" ? Tout simplement, composer une fonction avec une autre afin de gérer partiellement les arguments de la première fonction.

Le cas le plus classique est la fonction "partial" que nous pouvons trouver dans Lodash. Par exemple, nous avons la fonction "greet":


function greet(greeting, name) {
  console.log(greeting + ', ' + name);
}

greet('Hello', 'Heidi'); //'Hello, Heidi'



Nous allons faire en sorte que le premier paramètre soit gérer "naturellement" (afin de n'avoir qu'à spécifier par la suite que le nom):


function greetCurried(greeting) {
  return function(name) {
    console.log(greeting + ', ' + name);
  };
}

var greetHello = greetCurried('Hello');
greetHello('Heidi'); //'Hello, Heidi'
greetHello('Eddie'); //'Hello, Eddie'



Et voici la version Lodash:

var greetHello = _.partial(greet, 'Hello');
greetHello('Heidi'); //'Hello, Heidi'
greetHello('Eddie'); //'Hello, Eddie'



Et enfin la version Ramda:

var greetHello = R.partial(greet, ['hello']);
greetHello('Heidi'); //'Hello, Heidi'
greetHello('Eddie'); //'Hello, Eddie'


Commentaires

Posts les plus consultés de ce blog

ISO: liens & outils utiles

NodeJs et SSL: une petite analyse

Créer sa commande slack en quelques minutes