DEV Community

Cover image for Functional Programming (FP) Principles with examples
Flavio Rosselli
Flavio Rosselli

Posted on • Edited on

Functional Programming (FP) Principles with examples

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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!"
Enter fullscreen mode Exit fullscreen mode

Top comments (0)