Functional Programming With Javascript: Pipe, Go

Woohyun Jang
2 min readDec 2, 2020

Last time, we prepared ingredient to make pipelining functions. Let’s implement it in earnest.

Pipe

Pipe function ties up pure functions. It takes plural functions, and return a single function. The returned function executes input functions in order.

For example, look at this code.

test('pipe', () => {  const squareOnlyOdds = pipe(    (collection) => filter(collection, value => value % 2),    (collection) => map(collection, value => value * value),  );  expect(squareOnlyOdds([1, 2, 3, 4, 5, 6])).toStrictEqual([1, 9, 25]);});

We put two functions. The first one takes a collection and returns the result filtered only odd numbers. The second function likes the first one. But it returns squared numbers.

Then, how can we implement the ‘pipe’? Pipe function takes multi-functions as parameters and returns just one function as a value. Don’t you think we saw it anywhere? It likes to ‘reduce’. Maybe we can use it!

// functions/pipe/index.jsconst reduce = require('../reduce');
function pipe(...fns) { return (collection) => reduce(fns, (prevResult, fn) => fn(prevResult), collection);}module.exports = pipe;

Go

The pipe function returns a new function that is contains all input functions. Sometimes we want to put the data, excute directly and get return value. In this case, there is a ‘go’ function like this.

test('go', () => {  const squaredOdds = go(    [1, 2, 3, 4, 5, 6],    (collection) => filter(collection, value => value % 2),    (collection) => map(collection, value => value * value),  );  expect(squaredOdds).toStrictEqual([1, 9, 25]);});

It’s similar to ‘pipe’ but we put the collection this time. The result is also result collection, not a function. It’s not to hard to make this function. We just have to get the additional parameter, collection. And excute it.

const pipe = require('../pipe');function go(collection, ...fns) {  return pipe(...fns)(collection);}module.exports = go;

Use curring

Pipe & Go functions are implemented successfully. Now, we’re going to make codes pritter. Last time, we made curry & curryr. It supports functions to receive iterable and iteratee separately.

If we wrap functions like map, filter and so on by ‘curryr’, they can receive iteratee function first. So we can extract wrapper function in ‘pipe’ or ‘go’ functions.

test('pipe', () => {  const squareOnlyOdds = pipe(    filter(value => value % 2),    map(value => value * value),  );  expect(squareOnlyOdds([1, 2, 3, 4, 5, 6])).toStrictEqual([1, 9, 25]);});test('go', () => {  const squaredOdds = go(    [1, 2, 3, 4, 5, 6],    filter(value => value % 2),    map(value => value * value),  );  expect(squaredOdds).toStrictEqual([1, 9, 25]);});

Codes are more simple and readable. Now we can chain the functions easily.

This style is very powerful. In modern web service, There is a lot of work to manipulate data. We have to sort, filter, replace, and all these functions at the same time. In pipelining, we can build logic and maintenance simple.

Github Source Code

--

--