The concept of "pipes" or "pipelining" in JavaScript is a functional programming concept where you pass the output of one function as the input to the next function, forming a pipeline of functions. Here are some real-world examples:
-
Data Transformation: Suppose you have an array of objects representing users, and you want to transform this data in several steps (e.g., filter out inactive users, sort by last name, and then extract just the email addresses). Each of these steps could be a function, and you could use
pipes
to create a single function that performs all these transformations in order. -
Middleware in Express.js: In Express.js, middleware functions are used to handle requests and responses. These middleware functions are essentially a pipeline where each function receives a request and response object, does something with them (like checking if a user is authenticated), and then passes them on to the next middleware function.
-
Redux Middleware: In Redux, middleware is used to handle side effects and asynchronous actions. Middleware functions in Redux form a pipeline where each function can inspect and modify actions before they reach the reducer.
-
Data Validation: Suppose you have a form and you want to validate the input in several steps (e.g., trim whitespace, check if the input is empty, validate against a regex). Each of these steps could be a function, and you could use
pipes
to create a single validation function. -
Mathematical Computations: If you have a sequence of mathematical operations that need to be performed in a specific order, you can create a function for each operation and use
pipes
to combine them into a single function.
In all these examples, the pipes
function allows you to create modular, reusable functions and combine them in flexible ways.
https://bigfrontend.dev/problem/what-is-composition-create-a-pipe
what is Composition? It is actually not that difficult to understand, see @dan_abramov 's explanation.
Here you are asked to create a pipe()
function, which chains multiple functions together to create a new function.
Suppose we have some simple functions like this
const times = (y) => (x) => x * y;
const plus = (y) => (x) => x + y;
const subtract = (y) => (x) => x - y;
const divide = (y) => (x) => x / y;
Your pipe()
would be used to generate new functions
pipe([times(2), times(3)]);
// x _ 2 _ 3
pipe([times(2), plus(3), times(4)]);
// (x _ 2 + 3) _ 4
pipe([times(2), subtract(3), divide(4)]);
// (x \* 2 - 3) / 4
notes
- to make things simple, functions passed to
pipe()
will all accept 1 argument
/**
* @param {Array<(arg: any) => any>} funcs
* @return {(arg: any) => any}
*/
function pipe(funcs) {
return function (n) {
let result = n;
for (let func of funcs) {
result = func(result);
}
return result;
};
}
const addTwo = (n) => n + 2;
const divideByFive = (n) => n / 5;
const multiplyByTwo = (n) => n * 2;
const multiplyByThree = (n) => n * 3;
const addTwoMultiplyByThree = pipe([addTwo, multiplyByThree]);
console.log(addTwoMultiplyByThree(5)); // 21
const addTwoDivideByFive = pipe([addTwo, divideByFive]);
console.log(addTwoDivideByFive(5)); // 1.4
const addTwoMultiplyByThreeDivideByFive = pipe([
addTwo,
multiplyByThree,
divideByFive,
]);
console.log(addTwoMultiplyByThreeDivideByFive(5)); // 6