The difference between partial application & currying

As I’m working my way through Functional Javascript[1] (currently on chapter 5) I only now feel as though I understand what separates partial application from currying, I believe the main reason is that coming from an OOP background I think it takes quite some time to get used to functions playing such a critical role and the idea of functions taking other functions as parameters and returning functions from functions[2] is a large step away from objects being the focus point they are in OOP.

Once you get passed this first hurdle it then becomes easier to breakdown a Higher-Order Function and to be able to start see the signature[3] and how you can use either partial application or currying to created configured re-usable functions.

To illustrate how we can use currying to create re-usable functions I will need a volunteer function[4]:

var changeCasing = function (items, prop, upper) {
  var results = [];
  var len = items.length;
  for (var i = 0; i < len; i++) {
    var item = items[i];
    var val = item[prop];
    item[prop] = (upper) ? val.toUpperCase() : val.toLowerCase();
    results.push(item);
  }
  return results;
};

If this is not making you scream out use map or at least forEach you may want to come back after learning more about functional programming, aside from the fact this function is not utilizing any functional programming we can still wrap it up to use currying then with some tweaks partial application.

First we need some data to supply to it:

var data = [
    {id: 1, name: 'joe'},
    {id: 2, name: 'bob'},
    {id: 3, name: 'jill'},
];

So if I want to transform the name of the user into upper case as is the case here, it’s simply:

var upperCaseNames = changeCasing(data, 'name', true);

However we have a lot of repeating parameters that are always the same for this data array (the upper bool flag and the property name) we would like to pre-populate these parameters and then just be able to call the function providing the data array.

Currying

We can achieve this by modifying the changeCasing function to this[5]:

var changeCasingCurryable = function (upper) {
  return function (prop) {
    return function (items) {
      var results = [];
      var len = items.length;
      for (var i = 0; i < len; i++) {
        var item = items[i];
        var val = item[prop];
        item[prop] = (upper) ? val.toUpperCase() : val.toLowerCase();
        results.push(item);
      }
      return results;
    }
  }
};

Don’t worry I remember how I felt first time I saw code like this and goes back to my first point, notice however that once we get passed the nested function code the main body has not changed at all and we can call it via:

var upperCaseNames = changeCasingCurryable(true)('name')(data);

There are a few things to note here:

  1. We now have a separate function call for each argument expected
  2. I modified the changeCasing function so that we accept the parameters from right-to-left[6] which is why the upper bool flag is in the first call

Now we can start to reap the benefits of the modified function, let’s got through supplying values for each function call:

var upper = changeCasingCurryable(true);
// now I have a version that will always change the property provided to uppercase
var upperCaseNames = upper('name')(data);

var upperNames = changeCasingCurryable(true)('name');
// now I have a version that will always change the name property to uppercase
var upperCaseNames = upperNames(data);

Each time I’am providing just enough of the values I want to be applied and being handed back a function ready for the next value, once the values are all supplied the body is executed and I get the result back.

If we had to change each function like changeCasing to take advantage of currying this would be a major headache and require a lot of work when working with other libraries luckily we can take advantage of JS’s dynamic nature to build a generic functions that we can apply to a functions we want to curry:

var curry3 = function (fun) {
  return function (third) {
    return function (second) {
      return function (first) {
        return fun(first, second, third);      
      }
    }
  }
};

We can then change the changeCasingCurryable to be:

var changeCasingCurryable = curry3(changeCasing);

This function is explicit about the number of arguments to curry on, you can use the arguments variable to dynamically curry on the remaining arguments however this can cause you issues given the leniency JS has regarding function arguments.[7]

Partial Application

To demonstrate effective use of partial application, I will need to make some adjustments to changeCasing’s signature:

var changeCasing = function (upper, prop, items) {
//...
}

I have swapped the arguments so that the array of items are the last argument, this is the only change we need to make next we need a function we can use to apply partial application:

var partial = function (fun) {
  var partialArgs = Array.prototype.slice.call(arguments, 1);
  return function () {
    var remainingArgs = Array.prototype.slice.call(arguments);
    return fun.apply(fun, partialArgs.concat(remainingArgs));      
  }
};

This function takes the function we want to partially apply and also the parameters we want to fix the returned function then executes the function using the fixed parameters plus the passed into values, this can then be applied to changeCasing:

var changeCasingPartial = partial(changeCasing, true, 'name');
var upperCaseNames = changeCasingPartial(data);

There are a few things worth noting:

  1. Unlike the currying usage we don’t have a function returned for each argument, instead we can fix any number of parameters and the returned function is ready to be executed with the remaining parameters.
  2. Also unlike the currying usage we are dynamically applying the arguments rather than being explicit, this approach works well with JS’s lenient argument approach to function calls as we typically want to provide values for the first few parameters and then be able to provide the remaining at a later point.

Instead of using the custom partial function above you can also make use of the bind function[8] if it is supported in the target runtime, then the changeCasing above would change to:

var changeCasingPartial = changeCasing.bind(null, true, 'name');
var upperCaseNames = changeCasingPartial(data);

Note the context is supplied as the first parameter.

Conclusion

Both currying and partial application are very similar, they both return you back a function that has had one or more values bound to its parameters, however there are some notable differences:

  1. Currying can be performed on each argument in either direction, partial application is only performed left-to-right.
  2. Currying only deals with single argument functions, so we end up with a function for every argument we want to curry on. Partial application can be applied for any number of arguments, so you could provide every expected parameter and then the returned function could be executed with no parameters (although this would be of little use!)

  1. A great book for those wanting to learn about the functional programming paradigm but in a language which you already know
  2. Higher-Order Functions
  3. One way I have found it easier is by using a comment signature notation I have seen being used:
    //+ methodname :: input_type -> return_type
    //+ map :: fun(a -> b) -> [a] -> [b]
    

    I think it is based off other FP languages, to breakdown the map example:

    1. takes a function that expects any type as input and returns any type
    2. next it takes an array of the a type (passed to first function)
    3. finally returns an array of the b type (returned from first function)
  4. I really wanted to try and find a real world example however it always ended up with lots of other techniques detracting away from the main point of the post (I will try and get another post showing real world examples of functional programming in JS)
  5. The reason this is possible in JS is because of closures otherwise the nested function would not be able to capture the argument passed to it’s containing function
  6. Currying can be applied in either direction, I have chosen this direction because partial application always goes left-to-right so it emphasizes one of the key differences
  7. This is a demonstration to illustrate how you can get into trouble when not being explicit with function arguments.
  8. Bind Function
About these ads

3 thoughts on “The difference between partial application & currying

  1. Pingback: Compose & Sequence created using recursion & imperative | Journal of a software dev

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s