Friday, March 16, 2007

Currying, Closures ad how to screw your mind in 1 line of code

Ok, so we can pass functions as data using delegates. I recently started using delegates as return values for functions, and this can lead to some odd syntax!

So, the 1 line of code:

int answer = Add(5)(3);

Note the second set of brackets - where the hell did they come from!

So here's the add function

public static AddNumbers Add(int x)
return delegate(int y) { return x + y;};

where AddNumber is a delegate (function pointer) defined as:

public delegate int AddNumbers(int y);

What the hell does this mean?

When we call Add(5) we are doing two things:

1. Setting the variable x within the anonymous function's return statement
2. returning a function, which takes a parameter y

As the return value of Add(5) is a function we can then call the function Add(5)(3); which will return the value 8!

This leads to two important functional concepts:

1. Currying - a function which takes multiple parameters can now be split into multiple functions each taking one parameter i.e. Add(int x, int y) becomes Add(int x) : return AddNumber(int y)
using the stack to store the x variable

2. Closures - the anonymous method can "see" the variables within the Add(int x) method of which it is a part - just like the contents of an if statement would. The complexity here is when the anonymous function is returned from the Add function

We can use currying to intialize parameters. So for example lets say we wanted to do the following sums:

answer = 3 + 5
answer = 3 + 7
answer = 3 + 9

rather than do:
int answer1 = Add(3, 5);
int answer2 = Add(3, 7);
int answer3 = Add(3, 9);

we can initialise the 3 parameter using the Add function, and rewrite our code as:

AddNumbers adder = Add(3);
int answer1 = adder(5);
int answer2 = adder(7);
int answer3 = adder(9);

This becomes really useful when out initialization occurs in a different part of our code to the actual "running" of the code. It could also allow us to create an "immutable" function, where we initialize all of the functions parameters at one point in our code and return a parameterless function.


Post a Comment

<< Home