9/16 lessons56%

Function Composition

Function composition is a fundamental concept in functional programming. It’s the process of combining two or more functions to create a new function. This approach helps break down complex problems into smaller, reusable, and maintainable functions.

Function Composition

Chaining String Transformations

Suppose you need to process user input by trimming whitespace, converting it to lowercase, and replacing spaces with hyphens.

Without Composition:

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
          function trim(str) {
  return str.trim();
}

function toLowerCase(str) {
  return str.toLowerCase();
}

function replaceSpaces(str) {
  return str.replace(/\s+/g, '-');
}

const userInput = "  Hello World  ";
const step1 = trim(userInput);
const step2 = toLowerCase(step1);
const result = replaceSpaces(step2);

console.log(result); // hello-world
        

Using Function Composition:

javascript
1
2
3
4
5
6
7
8
9
10
          function compose(...functions) {
  return function (input) {
    return functions.reduce((acc, fn) => fn(acc), input);
  };
}

const processInput = compose(trim, toLowerCase, replaceSpaces);

const userInput = "  Hello World  ";
console.log(processInput(userInput)); // hello-world
        

Here, compose creates a pipeline for processing the input, making the code cleaner and more expressive.

Why Use Function Composition?

  1. 1
    Reusability: Combine smaller functions to create new, more complex functionality.
  2. 2
    Readability: Avoid deeply nested or repetitive function calls.
  3. 3
    Testability: Test individual functions independently and then verify the composition.

Advanced Example: Processing Arrays

Let’s process an array of numbers:

  1. 1
    Filter even numbers.
  2. 2
    Double the filtered numbers.
  3. 3
    Sum the resulting numbers.

Step-by-Step Implementation:

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
          function filterEvens(numbers) {
  return numbers.filter((num) => num % 2 === 0);
}

function double(numbers) {
  return numbers.map((num) => num * 2);
}

function sum(numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}

const numbers = [1, 2, 3, 4, 5, 6];

// Without composition
const evens = filterEvens(numbers);
const doubled = double(evens);
const total = sum(doubled);
console.log(total); // 24
        

With Function Composition:

javascript
1
2
3
          const processNumbers = compose(filterEvens, double, sum);

console.log(processNumbers(numbers)); // 24
        

Conclusion

We’ll expand on function composition in:

  • Chapter 5 Currying, where composed functions handle partial application.
  • Chapter 8 Advanced composition techniques and point-free style.