Currying and composition

Functional composition is something relatively new to me so here are some building blocks I developed to understand it better.

Higher order functions are something that JS developers like myself are familiar with but to make the step to richer functional composition we need some more tools in our utility belt. Here are two such simple tools I've been experimenting with.

Curry

A higher order function that turns a function with a number of arguments and returns a function that can be called with fewer arguments until they've all been supplied.

// Curry supplied function (simple arguments only, no optional or named)
const curry = (fn) => (...args) =>
  fn.length <= args.length ?
    fn(...args) :   // All required arguments supplied, return result
    curry(fn.bind(null, ...args)); // Missing args, return partial application

// Example
const sumThree = (a,b,c) => a+b+c;
const sumThreeCurried = curry(sumThree);
// All equiv:
sumThree       (1, 2, 3) == 6; // true (original)
sumThreeCurried(1, 2 ,3) == 6; // true
sumThreeCurried(1, 2)(3) == 6; // true
sumThreeCurried(1)(2, 3) == 6; // true
sumThreeCurried(1)(2)(3) == 6; // true

Flow

A higher order function that takes a number of functions and returns a new function that pipes the output of one into the input of the next.

// Compose supplied functions in natural order
const flow = (...fns) => (...args) =>
  fns.reduce(
    (acc, fn, i) =>
      i === 0 ?
        fn(...args) : // First run, return fn applied to supplied args
        fn(acc),      // Later run, return fn applied to previous result
    null // Initial accumulator value (forces uniform params to reducer)
  );

// Example
const inc = (a) => a+1;
const triple = (a) => a*3;
const incThenTriple = flow(inc, triple);
incThenTriple(4) == 15; // true
Published on: 18 Jan 2016