Functional programming (FP) is a programming paradigm that emphasizes the use of functions to create software. Unlike imperative programming, which focuses on performing tasks through structured sequences of statements, functional programming is declarative, meaning it describes what the program should accomplish without detailing how to achieve it.
This approach leads to code that is often cleaner, more predictable, easier to test, and less prone to bugs, avoiding changing-state and mutable data.
Key Principles of Functional Programming
1. Immutability
Data is immutable in FP, meaning it cannot be changed once created. If changes are needed, new data structures are created. This helps prevent side effects and makes code easier to reason about.
map
is a good example of immutability. It creates a new array without modifying (mutating) the original one.
const originalArray = [1, 2, 3];
const newArray = [...originalArray, 4]; // originalArray remains unchanged
// map example
const numbers = [1, 2, 3];
const doubledNumbers = numbers.map(n => n * 2);
console.log(numbers); // [1, 2, 3], original array is unchanged
console.log(doubledNumbers); // [2, 4, 6], new array created
2. Pure Functions
A pure function always produces the same output for the same input and has no side effects. This means it doesn't modify any external state.
const add = (a: number, b: number): number => a + b;
console.log(add(2, 3)); // 5, always returns the same value for given inputs
3. First-Class Citizens
Functions are treated as "first-class citizens", meaning they can be passed as arguments, returned from other functions, or assigned to variables.
const multiply = (x: number) => (y: number): number => x * y;
const double = multiply(2);
console.log(double(5)); // 10
4. Higher-Order Functions
A higher-order function takes one or more functions as arguments or returns a function. This enables powerful abstractions and code reuse.
map
, filter
, reduce
, and sort
are higher-order functions.
const applyOperation = (x: number, y: number, operation: (a: number, b: number) => number): number => operation(x, y);
const multiply = (a: number, b: number) => a * b;
console.log(applyOperation(4, 5, multiply)); // 20
// map, filter and reduce examples
const numbers: number[] = [1, 2, 3, 4];
const doubled: number[] = numbers.map((n) => n * 2);
const evens: number[] = numbers.filter((n) => n % 2 === 0);
const sum: number = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(doubled); // [2, 4, 6, 8]
console.log(evens); // [2, 4]
console.log(sum); // 10
Extra
Recursion and Function Composition are not a FP principle, but they walk together with it.
1. Recursion
Recursion is a function that calls itself with smaller inputs until it reaches a condition (base case). Functional programming often uses recursion to solve problems instead of loops.
const sumArray = (arr: number[], index: number = 0): number => {
if (index === arr.length) return 0;
return arr[index] + sumArray(arr, index + 1);
}
const numbers = [1, 2, 3, 4, 5];
const totalSum = sumArray(numbers);
console.log(totalSum); // 15
2. Function Composition
Combining simple functions to build more complex functions. This allows for more modular, reusable code.
const toUpperCase = (str: string): string => str.toUpperCase();
const exclaim = (str: string): string => `${str}!`;
// composition
const shout = (str: string) => exclaim(toUpperCase(str));
console.log(shout("hello")); // "HELLO!"
Top comments (0)