ES6 Recursion with Functional Programming

In this article, we are going to use ES6 recursion with functional programming to understand how we can implement list operations like map, reduce, filter and join.

Head & Tail

When functions are run recursively over lists, we can model those lists as a head and a tail.

The head is the first element of the list, and the tail is the rest.

const [ head, ...tail ] = [ 1, 2, 3, 4 ];
// head: 1
// tail: 2, 3, 4

In ES6, we can use destructuring for retrieving the tail as above.

Doing things functional, we can implement the head and tail functions.

const getHead = ([ head, ...tail ]) => head;
const getTail = ([ head, ...tail ]) => tail;

Recursion

(Tail) Recursion

We can implement functions that operate over arrays using parameter destructuring and recursion, for example map function.

List

Arrays are called lists in functional programming.

Let’s start by implementing the map function in ES6.

Map

Map takes a list and a function, and returns a list containing the result of the function applied to each element of the list.

function map([head, ...tail], fn) {
  if (head === undefined && !tail.length) {
    return [];
  } else {
    return tail.length === 0 ?
      [fn(head)] : [fn(head), ...map(tail, fn)];
  }
}

Line 5: the tail.length === 0 checks if there is still a tail to recurse over. Otherwise, the recursion stops there.

This function can be used to test like follows:

const items = [1, 2, 3, 4];

console.log(map(items, item => item + 1));
// 2, 3, 4, 5

Next, look at how we can implement filter method.

Filter

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

function filter([ head, ...tail ], fn) {
  const newHead = fn(head) ? [ head ] : [];
  return tail.length ? [ ...newHead, ...(filter(tail, fn)) ] : newHead;
}

This function can be used to test like follows:

const items = [1, 2, 3, 4];

console.log(filter(items, item => item % 2 === 0));
// 2, 4

Let’s look at the reduce method, next.

Reduce

The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.

function reduce([ head, ...tail ], fn, initial) {
  if(head === undefined && tail.length === 0) {
    return initial;
  }

  if(!initial) {
    const [ newHead, ...newTail] = tail;
    return reduce(newTail, fn, fn(head, newHead));
  }

  return tail.length ?
    reduce(tail, fn, fn(initial, head)) : [ fn(initial, head) ];
}

Finally, let’s look at the join method.

Join

The join() method joins all elements of an array into a string.

function join([ head, ...tail ], separator = ',') {
  if (head === undefined && !tail.length) {
    return '';
  }

  return tail.length ? head + separator + join(tail, separator) : head;
}

This function can be used to test like follows:

const items = [1, 2, 3, 4];

console.log(join(items));
// 1, 2, 3, 4

Conclusion

The functions we implemented are already in ES5 and above, but doing so in recursive functions in ES6 gives you an in-depth understanding on how to use functional programming and ES6 effectively

Be first to comment

Leave a Reply