July 27, 2012

Schönfinkelization

I was amused by the name when I came across this technique while reading the book Javscript Patterns by Stoyan Stefanov. Schönfinkelization is just another name for a technique called Currying, but somehow, this name seems cool, right? ;-)

To understand what Currying is, we first need to understand partial function application. Intuitively, it just means that “if I fix the first arguments of a function, I get a function that takes the remaining arguments”.

Currying then, is the process of making a function capable of handling partial application. The basic idea of Currying is to transform a function requiring n arguments into a chain of functions, each taking a single argument. This allows us to fix the first few arguments to get a new function that will take the rest of the arguments, which is exactly what we need for partial application. In the book, Stoyan gave a generic function schonfinkelize to enable this behavior for all such functions -

function schonfinkelize(fn) {
  var slice = Array.prototype.slice,
    oldArgs = slice.call(arguments, 1);
  return function() {
    var newArgs = slice.call(arguments),
      args = oldArgs.concat(newArgs);
    return fn.apply(null, args);
  };
}

If you look carefully, most of the code is just there to get over the limitation that arguments is not an array but an array-like object. If arguments was an array, the function would’ve been much simpler, and then it is easier to see the gist of what the schonfinkelize function does.

// This is NOT working code. It assumes `arguments` is an array.

function schonfinkelize(fn) {
  var oldArgs = arguments.slice(1);
  return function() {
    return fn.apply(null, oldArgs.concat(arguments));
  };
}

Of course, once this generalized function is defined, it is easy to use it.

// Function that we want to schonfinkelize (or curry)
function multiply(a, b) {
  return a * b;
}

// Partial application
var multiplySc = schonfinkelize(multiply, 10);

// Final result
var result = multiplySc(10); // 100

REFERENCES:

  1. Javascript Patterns by Stoyan Stefanov
  2. Wikipedia - Currying