Skip to main content

Thinking Currying !!!

Currying is a mathematical concept based on lambda calculus. It is a technique of operating on a function (taking multiple arguments) by splitting and capable of chaining into a series of single argument functions. It is very similar to what a human would attempt to do on paper. For example, if you have to add numbers 1 through 10, what would you do? Class II mathematics....zero in hand, one in the mind, add 0 and 1, so 1 in the mind, then 2 in the hand, ...up to 10. So we compute the addition with one argument at a time.

In the programming world, it is realized by transforming a n-arguments function into a (n-1) arguments function, which takes the remaining one argument. This transformation when applied recursively on each of the single argument functions is the chaining of single argument functions that I discussed earlier. Needless to say, currying is a gift of the functional programming world. In simple words, functional programming is about building functions from other functions, and so functions are treated as first class citizens (like data).

If currying is just transforming a n arguments function into a single argument function, then extension method too is an example of currying.

public static bool Replace<T>(this IList<T> srcList, int position, T item) 
{ 
   // Imagine an implementation here.... 
}

So you would be using the Replace<T> above without explicitly passing the source list to the method; one argument less.

list.Replace(2, newItem);
// instead of Replace(ilistObj, 2, newItem) if extension method was not invented.

Isn't that right? Yes, but that is not the currying from the conventional standpoint of functional programming.

For samples, we will not use the devil (any functional programming language) itself; instead we will use C#, which provides functional programming facilities. Alright, let us curry.

int Add(int x, int y) 
{ 
   return x + y; 
} 

Or to be 'functional', we may (re)write: Func<int, int, int> adderFunc = (x, y) => x + y;

To curry out an increment function, we would write as follows:-

Func<int, Func<int, int>> Incrementer() 
{ 
   return num => Add(num, 1); 
} 

and we use it is as follows:-

var inc = Incrementer(); 
Console.WriteLine(inc(5)); 
Console.WriteLine(inc(12)); 

Is that not better and wise than writing Sum(5, 1)?

If currying is just transforming a n-arguments function into a single argument function, then we should be able to write a generic currying function.

Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(Func<T1, T2, TResult> fn) 
{ 
   return x => y => fn(x, y); 
} 

Func<int, Func<int, int>> Adder = Curry(Add); 
var Incrementor = Adder(1); 
var i = Incrementor(5); 

when we may not have actually  encountered a compelling situations to use this in the past

But isn’t this all cryptic? So why would we want to do all such cryptic things when we have not encountered any such situation....in the past? Actually we have.

When simple principles are tough for us to understand, it is our grandma who helps us. Our grandma here is C++; although grandma called it binding.

In C++, many STL algorithms require a functor (roughly equivalent to a function definition) with one argument, where as the desired function was a two or more arguments function. Then we use std::bind1st or std::bind2nd to curry it into unary function.

For instance, the count_if algorithm calculates the number of elements in a sequence that satisfy the predicate, which happens to be a unary function. Suppose we want to count the even numbers in a collection of whole numbers (and imagine this to be a tough calculation). If there was a function that could take a number and return true if it was an even number, it could be fed to count_if. But what if we had a function like the one below - a two argument function.

bool IsDivisible(int number, int divisor)
{
   return number % divisor == 0;
}

The functor we need is nothing but an IsDivisible function with the second argument as 2. We could write an IsEven function which in turn calls IsDivisible. But that could be tedious one we were write such wrappers for a function with 10 arguments. In situations like this, we curry. In C++, we (use) bind.

std::bind1st - A helper template function that creates an adaptor to convert a binary function object into a unary function object by binding the first argument of the binary function to a specified value.
std::bind2nd - A helper template function that creates an adaptor to convert a binary function object into a unary function object by binding the second argument of the binary function to a specified value.

So in our case, we will be using bind2nd, as follows:-

std::vector<int> wholeNumbers =  {
   1, 2, 4, 5, 6, 7, 9, 10, 12, 15, 17, 20
};

std::count_if(wholeNumbers.begin(),
   wholeNumbers.end(),
   std::bind2nd(IsDivisible, 2));

Unfortunately, C++ stayed with bind1st and bind2nd, and currying was not that evident or securely possible since C++ did not have required facilities, say something like delegates. So the concept has been in vogue from long time ago. Like every paradigm in programming, functional programming requires (re)aligning our thought (process). Instead of treating functions as just reusable pieces of code (as considered in procedural programming), they have to conceived as the input processors, which may return either data or whole new function; shrinked?

So that is a quick thought on Currying. I will try to share a few other thoughts related to currying, slightly expanding to functional programming but later.

2 comments

Popular posts from this blog

Passing CComPtr By Value !!!

This is about a killer bug identified by our chief software engineer in our software. What was devised for ease of use and write smart code ended up in this killer defect due to improper perception. Ok, let us go!CComPtr is a template class in ATL designed to wrap the discrete functionality of COM object management - AddRef and Release. Technically it is a smart pointer for a COM object.void SomeMethod() { CComPtr siPtr; HRESULT hr = siPtr.CoCreateInstance(CLSID_SomeComponent); siPtr->MethodOne(20, L"Hello"); }Without CComPtr, the code wouldn't be as elegant as above. The code would be spilled with AddRef and Release. Besides, writing code to Release after use under any circumstance is either hard or ugly. CComPtr automatically takes care of releasing in its destructor just like std::auto_ptr. As a C++ programmer, we must be able to appreciate the inevitability of the destructor and its immense use in writing smart code. However there is a difference between …

out, ref and InvokeMember !!!

When I was working on the .NET reflection extravaganza thing that I explained in my previous column, i learnt one another interesting thing, that is about the Type.InvokeMember. How will pass out or ref parameters for the method invoked using Type.InvokeMember ? If you are going to invoke a method with the prototypeint DoSomething(string someString, int someInt);then you would use InvokeMember like this:-object obj = someType.InvokeMember("DoSomething",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
this,
new object[] {"Largest Integer", 1});or use some variables in the new object[] {...}. But what do you with the args if DoSomething takes out or ref parameters ?int DoSomething(out string someString, ref int someInt);Something like this will not work string someText = string.Empty;
int someInt = 0;
object obj = someType.InvokeMember("DoSomething",
BindingFlags.Public | BindingFlags.NonPublic …

Offering __FILE__ and __LINE__ for C# !!!

THIS POST USES SYNTAXHIGHLIGHTER AND HAS ISSUES RENDERING CODE ONLY IN CHROME
Not the same way but we could say better.
Visual Studio 2012, another power packed release of Visual Studio, among a lot of other powerful fancy language features, offers the ability to deduce the method caller details at compile time.
C++ offered the compiler defined macros __FILE__ and __LINE__ (and __DATE__ and __TIME__), which are primarily intended for diagnostic purposes in a program, whereby the caller information is captured and logged. For instance, using __LINE__ would be replaced with the exact line number in the file where this macro has been used. That sometimes beats the purpose and doesn't gives us what we actually expect. Let's see.

For instance, suppose you wish to write a verbose Log method with an idea to print rich diagnostic details, it would look something like this.
void LogException(const std::string& logText, const std::string& fileName, …