Functional programming has gained a lot of traction over the years, along with the growing trend of functional/hybrid programming languages including F#, Scala, Clojure and Haskell to name a few. I wanted to re-explore functional programming – Can it really reduce bug count? Is it here to stay, or is it just one of those things that becomes a trend and die out after a few years?
What is Functional Programming?
Before I start, let’s first try to understand what functional programming is.
Functional Programming is a programming paradigm that avoids side effects by computing for results rather than performing actions.
Functional Programming and Object Oriented Programming try to solve the same problem using a completely different approach – they both try to reduce code complexity, on one hand, Object Oriented Programming tries to reduce complexity by encapsulating side-effects, Functional Programming, on the other hand, does this by getting rid of side effects altogether.
If you use C#, chances are, you already write some of your code in a functional style – that chained LINQ methods that you’ve used to transform your dataset – that’s been written in a functional way, there are no mutations happening, and the technique via method chaining is very similar to that of piping in FP. You are essentially passing functions over your dataset.
This is how we usually use LINQ.
(new int[] {0, 1, 2, 3, 4})
.Where(x => x > 2)
.Select(x => x * 2)
We are iterating over our dataset, passing in functions to compute a new result and we’re chaining functions to iterate over the last result. In no way did we mutate our initial data.
Higher Order Functions with Generic Delegate and Lambda
The introduction generic delegate and lambda in C# is what really allows writing in functional style code. This allows you as a developer to write code that no longer requires writing method or interface to handle an event, you can pass and return functions as you would in a functional language. When you pass or return functions, this is known as a Higher Order Function.
Expressions over statements
When writing in a functional way, expressions should be favoured over statements.
What is a statement? statements are usually controlled by logical if
and loops such as foreach
or for
statements, whilst in expressions, this tends to be done with ternary operator, null coalescing operator and passing functions over our data such as filtering and mapping.
Why does this matter? Simple, it’s more expressive, you are saying ‘I want to transform this to something else’ instead of ‘I want to do some operations to what I’m passing’ – you are wanting to do calculations rather than operations, you are wanting new data to be returned, not an action that can potentially try to mutate data.
Closure
“A closure is a persistent scope which holds on to local variables even after the code execution has moved out of that block.”
stackoverflow
You create a closure when you create a function that persists the state of a variable even after the parent block has already been executed.
How NOT to create a closure:
void Main()
{
var funcs = new List<Func<int>>();
for(var i=0; i < 10; i++) {
funcs.Add(() => i);
}
foreach(var func in funcs) {
Console.WriteLine(func()); // writes 10, ten times
}
}
As you go through the for
loop, i
is passed as a reference to our lambda causing it to use the final value of i
.
Here is a simple example of Closure in action:
void Main()
{
var funcs = new List<Func<int>>();
for(var i=0; i < 10; i++) {
var j = i; // copy
funcs.Add(() => j);
}
foreach(var func in funcs) {
Console.WriteLine(func()); // writes 0 to 9
}
}
We have created multiple functions that persist its own state – from 0
to 9
.
So why is this concept important in functional programming?
Well, this allows for functions to be much more transferable – this allows functions to be passed around and act like an object
persisting a state. You will see this effect used in the Currying
example.
Currying
What is Currying?
“A curried function is a function of several arguments rewritten such that it accepts the first argument and returns a function that accepts the second argument and so on. This allows functions of several arguments to have some of their initial arguments partially applied.”
stackoverflow
In OOP, if you were to write a static method that has three parameters, you would write it in such a way that you would just accept all the arguments.
public static int myStaticMethod(int x, int y, int z)
{
return x + y + z
}
In most functionally languages, you could do it in the same way same way:
f (x, y, z) => x + y + z
In a curried function, this would look something like this:
public static Func<int, Func<int, int>> myFunc(int x)
=> (y)
=> (z)
=> x + y + z;
Notice that the result an actual result is not returned until f(z)
is called. This function would be called and chained like so myFunc(2)(3)(4)
.
So how does this make it any better than just passing three arguments directly? Well, now we’re creating a Closure for each argument needed for this calculation, so we can actually start making use of this along with Higher Order function to do multiple calculations.
void Main()
{
var partial = myFunc(4)(4);
var sum1 = partial(1).Dump();
var sum2 = partial(2).Dump();
var sum3 = partial(3).Dump();
var sum4 = partial(4).Dump();
}
public static Func<int, Func<int, int>> myFunc(int x)
=> (y)
=> (z)
=> x + y + z;
If you run this in LINQPad, you will get a result of 9 10 11 12
.
Further thoughts
I believe that hybrid Imperative/Functional Programming is the next step and will probably be the standard solution in the IT industry for years to come based on the languages currently gaining popularity such as Scala and Haskell along with the recent introduction of Lambda’s in Java. I am glad that FP being popularised and is given a serious consideration as an alternative approach to writing maintainable code that is quicker to both read and write.
I highly recommend watching Functional Programming with C# Pluralsight course by Dave Fancher if you want to see FP with C# in action.
Reference Materials
- The RedMonk Programming Language Rankings: June 2015
- C# In Depth – The Beauty of Closures
- StackOverflow – “What is a closure?”
- StackOverflow – “What is currying?”
- Pluralsight – Functional Programming in C#
- Quora – “What is Functional Programming?”
- CodeProject – Functional Programming in C#
- Dave Fencher – “Functional C# Chaining Async Methods