DEV Community

Cover image for Mastering Functional Programming: Immutability, Composition, Pure and Arrow Functions
Geampiere Jaramillo
Geampiere Jaramillo

Posted on

Mastering Functional Programming: Immutability, Composition, Pure and Arrow Functions

Functional programming has gained traction in modern development due to its ability to produce more predictable, modular, and testable code. In this post, we explore four fundamental principles: immutability, function composition, pure functions, and arrow functions.


๐ŸงŠ Immutability: Protect Your State

Immutability means that once a value is created, it cannot be changed. Instead of mutating data, we return new versions with the desired updates.

โœ… Why is it useful?

  • Prevents unpredictable side effects
  • Easier debugging and testing
  • Ideal for concurrent environments (like React or Redux)

โŒ Mutable example:

const user = { name: 'Alice', age: 25 };
user.age = 26; // Mutation
Enter fullscreen mode Exit fullscreen mode

โœ… Immutable example:

const user = { name: 'Alice', age: 25 };
const updatedUser = { ...user, age: 26 }; // New copy with changes
Enter fullscreen mode Exit fullscreen mode

๐Ÿ” Function Composition: Chain Your Logic

Function composition means combining small, reusable functions to build more complex logic.

const trim = str => str.trim();
const toUpper = str => str.toUpperCase();

const cleanAndCapitalize = str => toUpper(trim(str));

cleanAndCapitalize("  hello  "); // "HELLO"
Enter fullscreen mode Exit fullscreen mode

Or dynamically compose using a helper:

const compose = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);

const cleanAndCapitalize = compose(trim, toUpper);
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“Œ Benefit: cleaner, modular, and easily testable code.


๐Ÿฆผ Pure Functions: No Surprises

A pure function follows two rules:

  1. Always returns the same output for the same inputs
  2. Has no side effects (doesn't modify external variables or interact with I/O)

โœ… Pure function:

const add = (a, b) => a + b;
Enter fullscreen mode Exit fullscreen mode

โŒ Impure function:

let counter = 0;
const increment = () => ++counter;
Enter fullscreen mode Exit fullscreen mode

Advantages:

  • Easier to test
  • Fewer hidden dependencies
  • Can be memoized or cached

๐ŸŒฝ Arrow Functions: Elegant and Contextual

Arrow functions (=>) offer a concise way to declare functions in JavaScript and TypeScript. They also donโ€™t have their own this, making them perfect for callbacks.

โœ… Simple example:

const double = n => n * 2;
Enter fullscreen mode Exit fullscreen mode

๐Ÿง  Implicit return:

const sum = (a, b) => a + b;
Enter fullscreen mode Exit fullscreen mode

๐ŸŽฏ this behavior:

function Timer() {
  this.seconds = 0;

  setInterval(() => {
    this.seconds++;
    console.log(this.seconds);
  }, 1000); // `this` works correctly
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿงน Conclusion

Adopting functional principles like immutability, composition, and pure functions (along with arrow functions) helps you write more declarative, maintainable, and robust code. These ideas are especially powerful in modern frameworks like React, NestJS, or Redux, where predictable data flow is crucial.

Top comments (0)