Function Composition in JavaScript at Five Levels

Let’s tackle Function Composition in JavaScript.

  1. Child: Imagine you’re getting ready for school. There are certain steps you take in order, right? First, you brush your teeth. Then you put on your clothes. Then you eat breakfast. Finally, you grab your backpack. Each step is like a small job. We can think of each of these jobs like a small helper. In programming, we can make our own helpers (which we call functions). Now, suppose you have a helper for brushing your teeth, another for getting dressed, another for eating breakfast, and so on. Function composition is like if you had a big helper (a big function) that combines all these little helpers in order. So, when you call your big helper, it does everything for you!

  2. Teenager: You know in math, how you sometimes do one operation and then use the result for the next operation? Like, say you have to add two numbers, and then multiply the result by another number. You can think of each operation as a function. In programming, particularly in JavaScript, we have this cool thing called function composition. It’s like chaining operations, where the output of one function becomes the input for the next.

  3. Undergrad: Function Composition is a fundamental concept in functional programming, and JavaScript supports it beautifully. It’s the process of combining two or more functions in order to produce a new function. The output of one function is used as the input for the next. This allows you to create modular and reusable code. For instance, if you have a function ‘f’ and a function ‘g’, function composition allows you to create a new function ‘h’ where ‘h(x) = f(g(x))’.

  4. Grad Student: In JavaScript, function composition is a mechanism of combining multiple simple functions to build more complicated ones. The result of each function is passed to the next, creating a pipeline of functions. It’s a key aspect of functional programming and leads to highly modular, testable, and reusable code. Libraries like Ramda or Lodash provide methods like ‘compose’ or ‘flow’ that allow for easy chaining of functions.

  5. Colleague: Function Composition, a tenet of functional programming, is an integral part of JavaScript and allows us to build sophisticated functionality through simple, single-responsibility functions. It is the process of passing the return value of one function as an argument to another function. In JavaScript, we can compose functions manually or using utility functions provided by libraries like lodash’s _.flow(). This composability is leveraged in various design patterns, including middleware in Express.js and Redux reducers.

Richard Feynman Explanation

Imagine we have three people: Alice, Bob, and Charlie. Alice is a painter, Bob is a framer, and Charlie is a gallery owner. Alice creates a painting, Bob takes the painting and puts a frame around it, and then Charlie hangs the framed painting in his gallery.

In this scenario, each person performs a function, a specific job. Alice creates, Bob frames, and Charlie displays. Now, what if we want to describe the entire process from creation to display in one go?

We might say something like, “Charlie displays Bob’s framing of Alice’s painting.” In this case, we’re “composing” the functions of Alice, Bob, and Charlie. We start with Alice, take her result to Bob, then take Bob’s result to Charlie.

In JavaScript, this process of taking the result of one function and feeding it into another function is known as “function composition”. You can take a value, pass it through a series of functions, and get a final result. This is an incredibly powerful concept in JavaScript and in programming in general because it allows you to build complex operations out of simple parts, much like our art-making process.

Discussion

Function composition is a concept from the field of mathematics that we can also use in JavaScript. It’s about creating new functions by combining existing ones. Here’s a simple example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// Let's define two simple functions first
function double(x) {
  return x * 2;
}

function increment(x) {
  return x + 1;
}

// Now we create a function that takes two functions as arguments and returns a new function
function compose(f, g) {
  return function(x) {
    return f(g(x));
  }
}

// We can create a new function by composing double and increment
var doubleThenIncrement = compose(increment, double);

// Now we can use our new function
console.log(doubleThenIncrement(5)); // output: 11, because (5 * 2) + 1 = 11

In the above code, doubleThenIncrement is a new function created by composing the double and increment functions. The compose function takes two functions f and g, and creates a new function that, when called with an argument x, first applies g to x, and then applies f to the result. This is a simple form of function composition.

Is compose function an example of currying?

No, the compose function is not an example of currying, though it’s related. Both are higher-order functions (functions that operate on other functions), but they’re used for different purposes.

Currying is the process of transforming a function with multiple arguments into a sequence of functions each with a single argument. For example, if you have a function that adds two numbers, currying that function would result in a function that takes one number and returns a function that takes the second number and returns the sum.

Here’s a simple example of currying:

1
2
3
4
5
6
7
8
function add(a) {
  return function(b) {
    return a + b;
  };
}

const addFive = add(5);
console.log(addFive(3)); // Output: 8

In contrast, function composition is the process of combining two or more functions to create a new function. The compose function in the previous example is performing function composition.

While they are different concepts, currying and function composition can often be used together in functional programming. You might curry a function to prepare it for composition, for example.

In function composition f(g(x)) is not equal to g(f(x)) ?

Correct. In mathematics and functional programming, function composition refers to applying one function to the result of another. Given two functions f and g, composing them in the order (f ∘ g)(x), or f(g(x)), generally won’t yield the same result as (g ∘ f)(x), or g(f(x)).

Here’s a simple example to illustrate this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function double(x) {
  return x * 2;
}

function increment(x) {
  return x + 1;
}

console.log(double(increment(3))); // Output: 8
console.log(increment(double(3))); // Output: 7

In the first console.log, we’re incrementing 3 to 4, then doubling it to get 8. In the second, we’re doubling 3 to get 6, then incrementing it to get 7. The two composed functions produce different results.