How to connect function in Javascript: Pipelining and composition

ivan khabuyhe
ThinkPhix
Published in
3 min readJun 13, 2022

In this article, I will take you back to the core of functional programming. I will teach you how to create sequencial function calls to come up with complex results from simple components.

What you’ll learn:

· Pipelining: Joining function in a fashion similar to pipes. A common technique in Linux pipes

· Chaining: Restricted to objects but a variant of pipelining

· Composing: Similar to pipelining but in an opposite order.

· Debugging: How do we debug pipeline and composition functions

All these techniques combined make your code efficient and cleaner.

Pipelining

Piping is a common programming technique used in UNIX systems. It’s away of making the output of a given function become the input of the next function.

According to Doug Mclloy, the creator of this pipelining principle concept:

· Each program should do one thing well

· Output from one program is expected to be input of another

In FP, we are often required to build more complex operations out of simple, single-purpose shorter functions.

The Unix shell uses this principle to apply pipelining.

Input -> f1() ->f2()->f3()-> …->fn()-> result

To showcase how pipelining works, consider the following functions

//function 1

const add5 = (n) => n + 5;

//function 2

const add10 = (k) => k + 10;

//function 3

const add15 = (l) => l + 15;

Simple pipelining

To build a pipeline of only two functions, you can write your function like the one below:

const pipe = (f, g) => (...args) => g(f(...args));const sum = pipe(add5, add10);sum(5);

Complex pipelining

There are cases where you need to pipeline more than two functions.

const pipe2 = (...fns) => fns.reduce((result, f) =>(...args) => f(result(...args)));
pipe2(add5, add10, add15)(5);

Problems with pipelines

One of the biggest challenges with pipeline technique is debugging your code. This is because you can’t really see what’s passed from one function to another.

How do you debug your code?

There are 3 ways you can debug pipelines.

For this article, I will teach you how to use a wrapper function. It wraps each function in the pipeline and logs the output.

const debugPipeline = (fn, logger = console.log) => (...args) => {logger(`entering ${fn.name}: ${args}`);try {const valueToReturn = fn(...args);logger(`exiting ${fn.name}: ${valueToReturn}`);return valueToReturn;} catch (thrownError) {logger(`exiting ${fn.name}: threw ${thrownError}`);throw thrownError; }};pipe2(debugPipeline(add5), debugPipeline(add10), debugPipeline(add15))(5)

Now that we have learnt how to use pipelining and how to debug it. Let’s move on to composition.

Composition

The concept of composition is similar to pipelining but it originates from mathematics theory. The sequence of functions in the pipeline technique is reversed.

For (k . l . m):

You should read it as k after l after m so that it is clear that m is the first to be applied, l next and k last.

const compose = (...fns) =>fns.reduceRight((f,g) => (...args) => g(f(...args)));compose(add15,add10,add5)(5);

Composition can also be debugged using the wrapper function we created above.

Conclusion:

As functional programming grows in popular. Composition and pipelining are wonderful tools to have in a Javascript developer’s arsenal. However please remember it’s not a silver bullet to each and every programming challenge. You can always consider the cons and pros of each programming technique and implement the best solution to your challenge.

--

--