Functional Programming
Every once in a while you come across a thought that changes the way you write code. Functional programming has been one of those paradigm changes. I guess the reason why I am so excited about functional programming is that as I have grown as a professional developer I naturally find myself solving problems in a functional manner. I think it is a good thing to systematicly solve problems. Not every architecture or problem is a good fit for a functional approach. But I do think that most programming could be greatly improved by approaching problems from a functional programming paradigms.
What are the basic tenants of Functional Programming?
Functions are objects. This was not a new concept to me, but I was not used to solving problems in this way. In Object Oriented Programming the paradigm is all about the classes, interfaces and contracts. We pass around objects and objects have functions. The thought that one could write a function that takes a collection of functions as the parameters and returns a new anonymous function is really foreign to the OO paradigm.
Lets first start by examining a typical imperative approach to creating an ading machine. Lets take the class ArithmaticMachine. This object has two properties (doAdd and doSubtract) and a method Calc(). This is not an uncommon approach to building an object that will either Add or Subtract. This behavior of the Calc function depends on the state of the object's properties.
class ArithmaticMachine
{
public bool doAdd = true;
public bool doSubtract = false;
public int Calc(int x, int y)
{
int number = 0;
if(doAdd)
number = x + y;
else if(doSubtract)
number = x - y;
return number;
}
}
Functional programming hates state. A function should be deterministic - it must produce the same result every time it is called (given the same set of parameters, of course). This approach has a number of benefits. The first and most important to me is readability. Code composed in this manner is much easier to read because it is a self contained unit of logic. It is much easier to unit test. You know that, given a set of parameters, the object will behave in the same manner. So what would a Calc method look like in Functional programming?
public static int Calc(int x, int y, Funcformula)
{
return formula(x,y);
}
Calc(5,6, ((x,y) => x + y)); // Add
Calc(5,6, ((x,y) => x - y)); // Subtract
If you are like me, when I first started learning about lambda expressions I hardly recognized it as C#. The above code creates a Calc function that takes three parameters, two ints (x, y) and a Func
To use our new Calc function, we call Calc() like normal except the third parameter is a Linq lambda expression. A lambda expression is really just a short hand way to create an anonymous function. Our lambda expression takes two int parameters and returns an int. Funny, that is exactly the type of function we need to have to pass to the Calc function. (Remember functions are objects too.)
Once you get passed the "newness" of the lambda expressions, functional programming really is much more expressive. And it is fewer lines of code.
So pure functions forbid state and they have no side effects. What is a side effect? Pure functions will never alter an object outside of its local scope nor will they alter the parameters passed in. For example a pure function would never take an object and modify one of the properties.
public static void Append(System.String text, string moreText)
{
text = text + moreText;
}
System.String text is passed by reference, which means that our function can change the state of the object. Why is this bad? Because I may not always be aware of the side effects. If I pass a more complex object into a function I may not be aware of the nuances of the business logic and how it will affect my object. Lets look at a more realistic example. Lets say we have a Person object. And lets also say our Person object has a Health property that describes our person's state of health.
if(person.Health.HasUlcer)
TakePeptic(person);
But what I didn't realize is that TakePeptic() also increases the person.Health.BloodPreasure. So later on in my code ...
if(person.Health.BloodPreasure > 100)
Kill(person);
So needless to say side effects can be a very, very bad thing.
Did I cover it all?
Not by a long shot. There are many other concepts to explore in functional programming. I am still exploring a few myself. But this is a worth while endeavor that will take your development skills to the next level. Look for more articles on this topic.