Functional programming is a declarative programming paradigm. Everything is treated as function in mathematics way and it does exactly only one action at a time. You can read more about it in wikipedia. It is not new now. It was introduced along with Object Oriented Programming.
Collection of simple functional blocks to build application with immutation, purity.
Simple understanding from mathematics:
f(x,y) = x + y
is just a function to add two numbers.
- f(x,y) does not change state (inputs)
- f(x,y) derives only output from inputs
- f(x,y) does only one action
Let's create another function which can add 3 numbers.
Something like this f(x,y,z) = x + y + z
.
Nope, I would suggest consider reusing existing f(x,y)
.
How can I reuse to add 3 numbers?
f1(x,y,z) = f(x,f(y,z)) or f(f(x,y),z)
Example:
f1(1,2,3) => f(f(1,2),3) => f(3,3) => 6
Similarly we can think of creating basic mathematical operations as functions:
Addition : f(x,y) = x + y;
Subtraction : s(x,y) = x - y;
Greater than: gt(x,y) = x > y;
Less Than: lt(x,y) = x < y;
Equal: eq(x,y) = x == y;
Not: not(x) = !x;
AND: and(x,y) = x && y;
ifElse: ifElse(cond,ifAns, elseAns) = cond ? ifAns : elseAns;
function: fn(f,a,b) = function(a,b){ return f(a,b); };
..etc
Instead of writing logical, we need to just use these basic mathematical functions to get output;
For example, If you have two numbers x & y and need to sum them if x greater than y otherwise subtract y from x.
How do you do:
const x = 1, y =2;
if(x > y)
print(x+y);
else
print(x-y);
In functional programming, you need to think of calling functions to do this.
const x=1, y=2;
ifElse(gt(x,y),f(x,y), s(x,y));
Let us understand the execution of fp way:
Stage 1: ifElse(gt(x,y),f(x,y), s(x,y))
Stage 2: ifElse(gt(1,2), f(1,2), s(1,2));
Stage 3: ifElse(1>2, 1+2, 1-2);
Stage 4: ifElse(false, 3, -1);
Stage 5: false ? 3 : -1;
Stage 6: -1 is output
It is as same as writing if else by ourself. But you can see lot of reusabilty of having function being called to perform some action than repeating the same for every need. It will be more readable if you start thinking from functional programming way. We will do more hands on this after understanding few supported new API in javascript.
A function which takes functions as arguments and returns a function which can process inputs and produces the desired out. It basically curries the inputs function to produce the desired function.
-
A function has no side effects in the system. It is created & used for simple purpose. It never changes / mutates state, global variables. It never logs anything, does CRUD operations with DB, IO devices..etc.
Function should not modify any global scope variables, inputs. It should produce new value / object instead. This is strict rule followed in functional programming.
If you remove function from the system, the side effect is zero except it's processing logic.
-
Looping with function to get desired result.
- I am done with theoary, lets talk about real time examples.
Javascript supports new prototype methods with Array which helps to implement functional programming without using any frameworks. We will understand few them here before starting with functional programming with javscript.
Array.prototype methods
- reduce
- map
- filter
- every
- some
- etc.. refer for more in MDN.
We can learn more theory from internet. Let start solving simple problems using them.
Lets assume below is dataset/input to the problem.
const numbers = [12,14,23,40,6,78,90,100,123];
Solution 1: Create a function which takes numbers array as argument and iterates it to find the maximum number in the array.
function max(numbers){
var max = numbers[0];
for(var i = 1 ; i < numbers.length ; i++){
if(input[i] > max) {
max = input[i];
}
}
return max;
}
console.log(max(numbers));
This works really perfect but we have introduced some new variables like max, i and using for loop. All these can be avoided.
Solution 2: Use Array.prototype.forEach to avoid for loop.
function max(numbers){
var max = 0;
numbers.forEach(function findMax(number){
if(max < number)
max = number;
});
return max;
}
console.log(max(numbers));
In this solution, we just replaced for loop with forEach which takes function as argument and uses it to process each item in array.
Improvements:
- we don't introduce & maintain variable like i
- we use callback function to process the array
Solution 3: Use Array.prototype.reduce, if you want to learn about reduce, please read in MDN
const reducer = (max, currentValue) => max < currentValue ? currentValue : max;
console.log(numbers.reduce(reducer));
In this soultion, we have removed for or forEach loop, reduce takes callback function and does recursion operation. reducer is a callback function which is invoked with two arguments, first argument is result of previous call, second argument is the current position value.
i.e) max is tha accumulator, numbers[i] is the currentValue from previous examples.
Improvements:
- don't need to have any global/local variables
- result derieved from function callbacks in recursion way.
- reducer becomes pure function & reusable
This is the way you start thinking in functional programming way. Functions are used to derived output from inputs.
We can solve this problem with for loop, Array.prototype.forEach. I would rather show you the solution directly using reduce.
const add = function(a,b) {
return a + b;
}
const sum = numbers.reduce(add,0);
- Add is simple function just return sum of 2 input numbers as arguments.
- Second argument 0 is initial seed to process first time.
Solution 1: Use forEach to filter odd numbers.
const odds = []
numbers.forEach( function(number) {
if(number % 2 == 1)
odds.push(number);
});
Solution 2: Use Array.prototype.filter
const isOdd = function (n){
return n % 2 == 1;
};
const odds = numbers.filter(isOdd);
filter API helps to filter item from array which satisfies the given condition. filter takes callback function and return result array.
Solution 1: Use forEach to filter odd numbers.
const sqrtNumbers = []
numbers.forEach(function(number) {
sqrtNumbers.push(Math.sqrt(number));
});
Solution 2: Use Array.prototype.map
const sqrtNumbers = numbers.map(Math.sqrt);
Array.prototype.map creates new array from input array by using given function.
I hope, we got fair understanding with javascript API to process the collection. We should be able to understand when to use map, reduce, filter..etc to keep modules simple.
Let get started thinking make functions to replace operators, comparators..etc