What is Functional Programming?
Functional programming (abbreviated as FP) is a programming paradigm in which programs are constructed entirely of pure functions, with no shared mutable state or side effects. We express what to do rather than how to accomplish it in functional programming, which is more declarative than imperative programming.
Real-World example is Declarative programming is a type of functional programming. It means that we announce what action job we will do without defining the particular actions we take to complete it.
A way of writing applications using only pure functions and immutable values. Click to explore about, Functional Programming
The Programming Timeline
Low Level & assembly |
First Compiler |
Functional (Declarative) |
OOP |
Procedural (Imperative) |
1940s |
1957 |
1958 |
1960s |
1972 |
Microcontrollers |
FORTRAN |
Lisp -> Clojure, Scheme, etc |
Simula |
C |
Programing Paradigms
- Procedural Programing (COBOL, BASIC, Pascal and C)
- Object-Oriented (Java, C++, Obj-C)
- Functional Programing (Lisp, Clojure, Scheme)
Sum top 10 expensive things from a list of 100 most expensive things
expensiveStuff.sort((first, second) => first.price - second.price);
let sum = 0;
for (let i = 0; i < expensiveStuff.length; i++) {
sum += expensiveStuff[i].price;
if (i >= 10) {
return sum;
}
}
};
Issues
- sort function mutates the array.
- The sum variable is mutable.
- Declaring the execution flow. We specify what should be done in each step.
const getTopTenSumt = (expensiveStuff) => (
[...expensiveStuff]
.sort((first, second) => first.price - second.price)
.slice(0, 10)
.reduce((total,item) => total + item.money, 0)
);
Pure Functions
- Given the same inputs and always returns the same output,
var xs = [1,2,3,4,5] xs.slice(0,3) // [1,2,3] xs.slice(0,3) // [1,2,3] |
var xs = [1,2,3,4,5] //not a function xs.splice(0,3) // [1,2,3] xs.splice(0,3) // [4,5] xs.splice(0,3) // [] |
- Has no side-effects
Side Effects
(What we get paid for, what customers care about, they don't care about code)A side effect is any change in the state of an application that is visible outside of the called function but not in its return value. The following are some of the side effects:
- Logging to the console
- Writing to the screen
- Writing to a file
- Triggering any external process
- Calling any other functions with side-effects
Functional programming is a significant paradigm shift in the software world over the past 10 years. Click to explore about, Reducing Maintenance Costs With Functional Programming
Immutability
The problem with the shared state is that you need to know every shared variable's history that the function uses or changes to understand its effects.
Problem 1: In JS, arrays, stacks, and maps are all mutable.
Solution: make all data structures immutable.
const a=Object.freeze({
foo: 'Hello',
bar: 'world',
});
a.foo='Namaste 🙏';
Output
//Error: Cannot assign to readonly property 'foo' of object Object
But frozen objects are only superficially immutable. For example, the following object is mutable:
const a = Object.freeze({
foo: { greeting: 'Hello' },
bar: 'world',
});
a.foo.greeting='Namaste';
console.log(`${a.foo.greeting},${a.bar}`); //'Namaste 🙏 ,world!'
USE: Immutable.js by Facebook
Make all Data Structures, variables immutable and use a copy of the existing data. But this creates another problem (copies). To overcome this, we use Persistent Data Structures like trie (immutable, supports copy operations without a lot of copies).
Curry
A curried function takes several parameters one at a time, returning a function that takes the next parameter, and so on until all parameters have been supplied. At this point, the application is finished and the final value delivered.
Binary and unary functions have different shapes. These forms are crucial, just as Lego pieces must fit together.
//unary
function Increment (x) {
return x;
}
//binary
function sum(x,y) {
return x +y;
}
Functional programmers love unary function, then binary.
Reusability Through Higher-Order Functions
What is a Higher-Order Function?
Any function that takes a function as an argument returns a function, or both is a higher-order function. Higher-order functions are frequently utilized in the following applications:
Abstract or isolate actions, effects, or async flow control using callback functions, promises, monads, etc.
Create utilities that can act on a wide variety of data types
Partially apply a function to its arguments or create a curried function for the purpose of reuse or function composition
function f(...args) {
return args;
}
function unary(fn) {
return function one(arg)
return fn(arg)
};
}
function binary(fn) {
return function two (arg1, arg2) {
return fn(arg1, args2);
};
}
var g = unary(f)
var h = binary(f)
g(1,2,3,4); //[1]
h(1,2,3,4); // [1,2]
Why do we want to curry?
We attempted to accomplish this using unary and binary functions. We lower the code's surface area; less code equals less surface area for bugs, resulting in fewer bugs. In the context of function composition, curried functions are convenient.
const add = x => y => x + y add(3)(2) |
function add(x) { return function(y) { return x + y; } } |
Immutability using curry
const request = default => options => {
options = Object.assign(
{ }, defaults, options
);
return fetch(option.url, options).then(res => res.json)
}
What is a partial application?
const add = (num1, num2) => num1 + num2;
const add3 = partial(add, 3) [function, default value]
const partial = (fn, ...args) => {
return (...otherArgs) => {
return fn(..args, ...otherArgs)
}
Setting up Continuous Delivery Pipeline for Continuous Integration and deployment of Scala Microservices application with Jenkins, Docker and Kubernetes. Click to explore about, Continuous Delivery Pipeline for Scala Application on Kubernetes
Composition
What is software development?
Breaking down a complicated problem into more minor problems and assembling simple solutions to generate a complete solution to the complex problem
- The act of putting together bits or elements to create a whole (general English)
- The process of applying a function to another function's output (programing)
In algebra,
(f o g)(x) = f(g(x)) // g is evaluated first
//normal
function minus2(x) {return x - 2}
function triple(x) { return x*3 }
function increment(x) { return x + 1 }
//add shipping rate
var tmp = increment(4);
tmp = triple(tmp);
totalCost = basePrice + minus2(tmp)
//Composition (right to left)
totalCost = basePrice + minus2(triple(increment(4));
// Better version (let's create abstraction)
shippingRate(x) {
return minus2(triple(increment(x));
}
//More better
function composeThree(fn3, fn2, fn1) {
return function composed(v) {
return fn3(fn2(fn1(v))));
}
var shippingRate = composeThree(minus2, triple, increment);
shippingRate(4)
Why Functional Programing in JAVASCRIPT
Javascript supports multi-paradigm, including functional, object-oriented, procedural, and prototypal programming.
FACT: In just ten days, Brendan Eich wrote the initial version of the language that would become JavaScript.
Why does JS support multiple paradigms?
Brendan Eich, who worked at Netscape Communications, created JavaScript in 1995. Brendan Eich's boss advised him to add Java Features because Java was popular at the time, and thus the problem began.
Java, Scheme, and Self-inspired JS.
- Scheme: Functional programming language (does not have this, objects) inspired from Lisp.
- Java: Object-oriented language
- Self: Object-oriented programming language based on the concept of prototypes. Self. began as a dialect of Smalltalk.
Problem
let Dog = {
sound: 'woof',
talk: function ( ) {
console.log(this.sound) //[this depends on where it is called]
}
}
dog.talk( ); //woof
let talkFunction = Dog.talk
talkFunction(); //undefined
let talkFunction = dog.talk
talkFunction(function does not have this) = dog.talk (method)
Solution
let boundFunction = talkFunction.bind(dog) [forcing this to be dog]
bindFunction( ) //'woof'
this -> context is important
Code splitting is the splitting of code into components or numerous bundles which can be loaded when there is a demand or in parallel. Click to explore about, Code-Splitting in ReactJs
What is the difference between Imperative and Declarative?
Functional programming is a declarative paradigm, meaning that the program logic is represented without explicitly stating the flow control.
Imperative programs spend lines of code detailing the particular actions used to get the desired outputs — flow control: how things are done.
Declarative programs abstract the flow control mechanism (the how) and spend lines of code explaining the data flow: What to do instead.
What are the goals, and why are they important?
Any time you write some code, that forces the person to execute it in their head. Its harder to understand, is harder to maintain, is harder to improve, is harder to fix.
Early | Declarative at some time earlier | Now this is declarative |
ar = [1,1,1,1] ar[0] +ar[1] +ar[2] +ar[3] |
sum = 0 for(i=0; i< ar.length; i++){ sum += ar[i]; } |
sum = 0; ar.forEach(num => sum + num) |
What is the difference between Procedures and Function?
The below highlighted are the differences between Procedures and Function?
Procedures
To perform a series of steps, a function can be invoked. A procedure is a name for the sequence, and procedural programming is the term for programming in this way.
The procedure can take (0-N) inputs, return (0-N) output, and be called multiple times.
Suppose it does not have a return keyword. Functions that don't have a return keyword are procedures. In JS, all functions minimally return the undefined value, undefined is also a proper output, but a relationship should be there between input and output.
Functions can only call functions. If they call procedure, they become procedure.
Functions
According to Set theory. A mathematical function is a relation between 2 sets, input set, and output set, and & its mapping between two sets. Every function is a single-valued collection of pairs. const toLowerCase = { “A”: “a”, “B”: “b”, ……}
Function Purity: There must be the same corresponding output for a given input. You can even plot functions.
f(x) = 2x^2 + 3 | function f(x) { // if you put x coordinate you get a y coordinate out return 2 * Math.pow(x,2) + 3; } |
Y = a(x)
What will be the value of x at the end?
A core part of Angular and one of its most significant features. Click to explore about, Angular Dependency Injection
How does ES6 uplift JavaScript in functional programming?
ES6 uplift JS in functional programming is explained below:
Alonzo Church: (professor of Alan Turing)
- Lambda expressions(anonymous functions)
const identity = x => x;
- Rest Operator
const array = (...elements) => {
return elements;
}
array(1,2,3); //1,2,3
- Spread Operator
const numbers = [1, 3, 5, 7];
function addNumbers(a, b, c, d) {
return a + b + c + d;
}
console.log(addNumbers(...numbers));
- Destructuring
const favSportsPlayers = ["Virat Kholi", "Ronaldo", "Messi"];
const [indiaTeamCaptain, ...footballPlayers] = favSportsPlayers
indiaTeamCaptain === "Virat Kholi"
footballPlayers[0] === “Ronaldo”
footballPlayers[1] === "Messi"
const head = ([x]) => x //const head=([x, ...rest]) => {return {x, rest}; }
head([1,2,3]) === 1
- Immutable Objects create new obj using Object.assign
Object.assign(
{ },
{ hello: 'Ankit' },
{ hi: 'Xenonstack' }
);
Conclusion
- Discover more about Functional Programming in Scala
- Discover more about Functional Testing and Its Types