Monday, March 10, 2014

Objects vs. Functions round 1: Currying vs. Instantiation

This article is about the difference between two Design Patterns: "FP Currying"  and "OO Instantiation". This is NOT about comparing the benefits of different programming languages, Object-Oriented, or Functional. We will use JavaScript examples to illustrate both patterns.

CAVEAT:  We will use the term "Currying" loosely here, to mean how we  would implement "something like it" in JavaScript.  It seems the proper definition of currying is calling a function with a subset of its arguments, and then getting back a function that has the previously given arguments fixed to the values you gave them.  The proper term for what we do below is "Partial Application"  meaning you pass in a function + some of its arguments into a function that returns a function where the given arguments have been fixed to values you gave.  You can read detailed explanation of the difference between currying and partial application here

It is often said the defining characteristic of Functional Programming (FP) is "Referential Transparency", or "immutability". But there is no reason why  OO "objects" can't be immutable.  And all FP languages must more or less allow things to "mutate", because they must deal with input-output in some fashion. A function that returns some data from the user most likely will return a different result the next time you call it.

For purposes of comparing FP and OO styles of programming I'd say the main difference is this:   In FP you create and call individual functions (which can return other functions).  In OO you create groups of functions called Classes which you then "instantiate" into Objects.


A well-known feature of FP is "currying" which loosely speaking means you can "fix" some of the arguments of a function to specific values to get another simpler function where those arguments will have the fixed values you gave. This means you don't need to re-enter that same value again and again.  "Currying" (or more properly "partial application") could be used in JavaScript  as follows:  

 function multiply (aNumber1, aNumber2){...}  
 var multiplyBy2 = curry(multiply, 2);
 var six         = multiplyBy2(3);

The benefit is that if you need to  multiply many different numbers by two you no longer need to pass both numbers as arguments of each call, one is enough. As mentioned the above is more "partial application" than "currying". But both serve the same purpose: Getting a simpler function out of a more complex one, by fixing some of the argument-values. I offer this characterization of the subtle difference between the two: "Currying is automated Partial Application"


So is there a way to achieve similar benefits with OO?  Yes. It is called instantiation. You define a "class" with a set of methods and a set of data and then "instantiate" it:

 function Multiplier () {...}    

 Multiplier.prototype.multiply = function multiply () {...}
 var multiplier2 =  new  Multiplier (2);
 var six         =  multiplier2.multiply(3);

Above  Multiplier  is the class,  multiplier2 its instance.

Based on the above examples it would seem currying is somewhat simpler. Fewer lines are needed. But what if you are looking for a solution that handles other numbers besides 2 as well?  The situation changes.

A Class is a group of functions parameterized  by the data defined for that class.   Therefore we can easily extend that group and add more functions or 'methods' to our class, to handle other calculations. So let's give our function/class a more general name, and  add methods for  different calculations:

 function Calc () {... }
 Calc.prototype.multiply = function () {...} 
 Calc.prototype.divide   = function () {...} 
 Calc.prototype.add      = function () {...} 
 Calc.prototype.subtract = function () {...} 
 Calc.prototype.raisedTo = function () {...} 

Then at runtime we can instantiate that class, with any number we want:

 var calcWith2 = new Calc (2); 

Feels a bit like currying, right?  If  we use traditional currying instead to create  multiple functions with a fixed parameter 2,  we  would write thus:

 var multiplyBy2 = curry(multiply, 2);
 ...
 var raisedTo2   = curry(raisedTo, 2);


Now imagine you need to handle other number as well: 3, 4, 5 , 99, etc.  What's so special about number 2 anyway?  Doing that by currying you need to apply currying to each function for each number we want to use as the fixed parameter:

 var multiplyBy3  = curry (multiply, 3);
 ...
 var raisedTo3    = curry (raisedTo, 3);

 var multiplyBy4  = curry (multiply, 4);
 ...
 var raisedTo4    = curry (raisedTo, 4);

 var multiplyBy5  = curry (multiply, 5);
 ...
 var raisedTo5    = curry (raisedTo, 5);

 ...

 var multiplyBy9  = curry (multiply, 9);
 ... 
 var raisedTo9    = curry (raisedTo, 9);



Using the OO -style we only need to write:

 var calcWith3 = new Calc (3);
 var calcWith4 = new Calc (4);
 var calcWith5 = new Calc (5);
  ...

With OO-instantiation we reuse the same parameter, say 4, and get a version of all  our math-functions, with a single call to instantiate the class Calc.  We don't need to re-curry all our methods for all numbers we need, 3,4, ... 99.  The advantage OO has is that the fixed  parameter 4 can be shared by ALL methods of the object-instance, by making a single call which creates that instance.

This benefit is not accidental.  It is a direct consequence of a defining feature of Object-Orientation: All functions ('methods') of an instance share the same set of data. Another way to put it:  By instantiating a class, you are currying multiple functions with a single call.

Which "pattern"  to use depends on what you need. If  you need a general, reusable, extensible solution, OO-style is the way.  If you just want a function that can multiply its argument by 2, currying is simpler. Especially if your language supports it. So I'm not saying "currying is bad". I'm saying it is not missed much in the Object-Oriented way of programming.

There are two additional benefits instantiation has over "currying" (or "partial application").  In a typical implementation of currying you can't curry an argument without currying the arguments before it as well. Can you?  Whereas with instantiation you can decide which subset of data-members of the instance you "fix" with non-default values.  Secondly if your language supports currying out of the box it can't support default arguments: If you don't provide a value for an argument, it doesn't mean a default value will be used for it. It means currying ensues.    


© 2014 Panu Viljamaa. All rights reserved  

UPDATE:  Thanks for several posters at Google+ who pointed out the subtle difference between "Currying" and "Partial Application".  I modified the text above to make it clear my use of the term 'currying' is technically incorrect.

3 comments:

  1. This is a cool idea worth sharing, though I'm definitely convinced that prototypical inheritance begins at Object.create and ends with functional closures.

    I'll probably do a blog post about it soon.

    ReplyDelete
    Replies
    1. Keep us posted on your upcoming blog-post. Thanks.

      Delete
  2. Currying is not more properly known "partial application". Currying refers to the nature of a functions arguments while partial application is when a function is "applied" to data, essentially equivalent to when a method gets called.

    ReplyDelete