In computer science, functional programming is a style of programming which models computations as the evaluation of expressions and avoids changing-state and mutable data, even if it's overwritten with new value, data must not changed.
Let's see the main concepts of functional programming, and we will show an example code written in C#.
// first-class function.
Func<int, int, int> add = (a, b) => a + b;
// higher-order functions.
Func<int, Func<int, int>> createAdder =
x => new Func<int, int>(
y => add(x, y)
);
var f = createAdder(2); // f(x) = x + 2
Console.WriteLine(f(1)); // 3
First-class function
First-class functions are functions that can be passed as arguments to other functions. You will seeadd()
in code example above.Func<int, int, int> add = (a, b) => a + b;
Higher-order functions
Higher-order functions are functions that can return functions. You will seecreateAdder()
in code example above.Func<int, Func<int, int>> createAdder =
x => new Func<int, int>(
y => add(x, y)
);
Pure functions
This is just normal functions, if we put in the same input many times, it will always return the same value, like theadd(1, 2);
will always return 3 as the value.Closures
Closures are any function which closes over the variable outside a function. example:x => new Func<int, int>(
y => add(x, y)
);
you will see it referencing variable x
from outside.Recursion
Recursion, or as many people know that recursive functions, is a function that calls itself until it resolves the problem. example with fibonacci:public int F(int n) => ((n == 0) || (n == 1))
? n : F(n - 1) + F(n - 2);
That's just an example with the simple concepts, in fact there is more than this.It seems hard and complicated? Let's see a simple way to implement functional programming.
The main key of simple way to do functional programming is:
- Look everything as the function that receives inputs and returns output as result.
- Avoid rewriting new data to variables, and do not mutate the state of objects.
So, why are the above concepts that are difficult to understand?
It's just tell that the language’s main paradigm is not a functional programming, but it supports functional programming paradigm.
So, I will show example from some actual work to refactoring c# legacy code to functional way.
Requirement: We have a method to validation oldest passenger age over 18 years old.
private bool IsPassengerBirthDateValid(Passenger[] passengers)
{
var result = true;
DateTime oldestDate = DateTime.MaxValue;
foreach (var passenger in passengers)
{
if (passenger.BirthDate < oldestDate)
{
oldestDate = passenger.BirthDate;
}
}
if (oldestDate > DateTime.Now.AddYears(-18))
{
result = false;
}
return result;
}
You'll see method there is doing something inside the loop to mutate an object in each loop. I need to refactor it to a functional way and avoid mutating the state of the object.private bool IsPassengerBirthDateValid(Passenger[] passengers)
{
var oldestDate = passengers.Min(passenger =>
{
return passenger.BirthDate ?? DateTime.MaxValue;
});
return oldestDate < DateTime.Now.AddYears(-18);
}
Look better? For me I say "Yes", we don't need to imagine what's going on with the current state inside the loopAfter the refactoring the code is easier to read in my opinion, and it can reduce the number of lines of code as well. In fact, we don’t refactor just inside the method, and we might restructure the design of the code too. If you write in a functional style it will be easier to test too.