Neues Node.js-Buch
Alle Artikel

Create a generic function for partial application from the right

Problem

You want to create a generic function, that produces for a given function the partial applied function, applying parameters from the right.

Ingredients

  • 2 functions
  • the apply method
  • the slice method

Directions

  1. Given: a generic function for partial application (see recipe 9) …

    function partial(fn /*, args...*/) {
      var args = Array.prototype.slice.call(arguments, 1);
      return function() {
        return fn.apply(this, args.concat(Array.prototype.slice.call(arguments, 0)));
      };
    }
  2. … which could also be written like this:

    function partial(fn /*, args...*/) {
      var args = Array.prototype.slice.call(arguments, 1);
      return function() {
        var argsInner = Array.prototype.slice.call(arguments, 0);
        var argsAll = args.concat(argsInner);
        return fn.apply(this, argsAll);
      };
    }
  3. To apply parameters from the right you only need to change the order how the argsInner and argsAll arrays are concatenated.

    function partial(fn /*, args...*/) {
      var args = Array.prototype.slice.call(arguments, 1);
      return function() {
        var argsInner = Array.prototype.slice.call(arguments, 0);
        var argsAll = argsInner.concat(args);
        return fn.apply(this, argsAll);
      };
    }
  4. Optional: write this again as an one-liner:

    function partial(fn /*, args...*/) {
      var args = Array.prototype.slice.call(arguments, 1);
      return function() {
        return fn.apply(this, Array.prototype.slice.call(arguments, 0).concat(args));
      };
    }
  5. Voilá, a perfect … oh, wait, you might want to rename the function to partialRight().

    function partialRight(fn /*, args...*/) {
      var args = Array.prototype.slice.call(arguments, 1);
      return function() {
        return fn.apply(this, Array.prototype.slice.call(arguments, 0).concat(args));
      };
    }
  6. Voilá, a perfect generic function that creates partial applicable functions starting from the right.

    function createPerson(firstName, lastName) {
      return {
       firstName: firstName,
       lastName: lastName
      }
    }
    var createPersonWithLastNameDoe = partialRight(createPerson, 'Doe');
    var johnDoe = createPersonWithLastNameDoe('John');
    console.log(johnDoe.firstName);  // "John"
    console.log(johnDoe.lastName);   // "Doe"

Alternative recipes

  • Since ES2015: use rest parameters as shown in recipe 15.

    const partial = (fn, ...args) => (...argsInner) => fn(...args, ...argsInner);
    const partialRight = (fn, ...args) => (...argsInner) => fn(...argsInner, ...args);