Related articles

How to write a compose function

JavaScript polyfill, by , Wednesday, June 25th, 2014

In this article I will show how to write a compose function. If you have used libraries like underscore.js or maybe its reversed twin scoreunder.js, you might have used and feel familiar with their compose function. What it lets you do is, to compose a new function out of an arbitrary number of other functions.

First I will spend a short time examining the differences in the implementations in underscore.js and scoreunder.js respectively, which then should lead us nicely into my own version, written using recursion.

compose in underscore.js vs scoreunder.js

If you look at the uncompressed code of underscore.js, you can find this implementation of the compose function similar to this;

  1. var compose = function() {
  2. var funcs = arguments,
  3. length = funcs.length;
  4. return function() {
  5. var idx = length - 1,
  6. result = funcs[idx].apply(this, arguments);
  7. while (idx--) {
  8. result = funcs[idx].call(this, result);
  9. }
  10. return result;
  11. };
  12. };

If you similarly look at the uncompressed code of scoreunder.js, you will find this implementation of the compose function;

  1. var compose = function() {
  2. var funcs = arguments;
  3. return function() {
  4. var args = arguments,
  5. length = funcs.length;
  6. while (length--) {
  7. args = [funcs[length].apply(this, args)];
  8. }
  9. return args[0];
  10. };
  11. };

An interesting difference between the two implementations is that in underscore.js the first function in the arguments list is called with apply, and its result stored to be used as argument for the other function calls, which are invoked with call. In the scoreunder.js implementation however, all functions are called with apply but the result is wrapped in an array literal, before passed as argument to the next function call.

This is two different ways of dealing with the fact, that arguments is an array like object and so in order to invoke a function with what ever it contains, you need to use apply. In underscore.js it is then presumed, that the return value from the function call is to be considered as one argument, hence the switch to using call. Even though the scoreunder.js implementation consistently uses apply they also assume that there will ever only be one argument to all but the first function invocation, as they are wrapping whatever is returned in an array literal. I am not arguing that this is either right or wrong, but merely making the observation, that the difference in implementation is more a question of preference than functionality.

compose function using recursion

Personally I do not see why, in this case, you would want to store the result of each function invocation, instead of just parsing it to the next, so in my implementation I avoid this using recursion;

  1. var compose = function() {
  2. var fn = arguments,
  3. length = fn.length;
  4. return function() {
  5. return (function form(arg) {
  6. return length ? form(fn[--length].apply(this, arguments)) : arg;
  7. }).apply(this, arguments);
  8. };
  9. };

Using this approach, what ever is returned from the previous function call is passed directly as arguments to the next function call, making only the one assumption, that the result you are interested in, is going to be the first argument of the last invocation of form.