Chapter 04 – Advanced Concepts

Chapter 04 - Advanced Concepts

Introduction

This section covers some advanced concepts that most seasoned JS programmers likely use but may not necessarily know that they come from the functional programming space.

Recursion

Recursion is simply the act of a function calling itself. In functional languages like Haskell, there are no looping mechanisms so your only way to “loop” through an iterable structure is to use recursion. If you remember back to Chapter 00, this is one of the features of functional programming in that it removes unnecessary statements in favor of expressions. 

spider man pointing

Building a recursive function is pretty straightforward and simply involves a base case for terminating the recursion (below,, this is done through decrementing the exponent but it can be any method of breaking out of the function) and of course some action to apply to each iterable value that at some point calls itself.

function power(base, exponent) {
  if (exponent == 0)
    return 1;
  else
    return base * power(base, exponent - 1);
}

// Outputs 19683
power (3, 9) 

However, we’re functional programming pros right now! We don’t use no looping! Let’s take our old friend “map()” and see if we can write our own version that does not use looping. Just as a refresher, “map()” takes a function and applies that function to modify each element of an iterable structure (typically an array) and returns a new iterable structure. 

function customMap(itt, fn) {
  // Base case, return empty iterable
  if(!itt.length){
    return [];
  }
  
  // Clone the iterable to avoid side effects
  const ittClone = JSON.parse(JSON.stringify(itt));

  // We need the first element
  const first = ittClone.shift();

  // Apply the function to the first element and use recursion to apply the rest
  return [fn(first)].concat(customMap(ittClone, fn));
}

const result = customMap([1, 2, 3, 4, 5], x => { return x * x });

// result -> [ 1, 4, 9, 16, 25 ] 

Let’s break down our new custom mapper!

  1. The customMap accepts two parameters: an iterable structure and a function to apply to each element.
  2. Within the function, we first create our base case so we don’t end up with never-ending recursion. In this case, if there are no more elements to the “itt” variable, we simply return an empty array.
  3. Next, we want to prevent any side effects since JS passes objects and arrays by reference so we clone the “itt” array.
  4. Now, with any given execution of our function, we’re only going to be applying the passed-in function to one element at a time so we only need the first element. Let’s “shift()” to get just the first element. This leaves the remaining elements of the array in “ittClone”…yes, “shift()” here is destructive!
  5. Finally, we have our recursion. Let’s break this down a bit:
    1. Our map function should always return an array so we first specify “return […]”.
    2. Since we’re only going to execute the function on one element, which we have from our “shift()” expression, we make that the first element of the new array.
    3. Now, there could be more elements to parse in the iterable and since we know our map function returns an array, we can use the “concat() ” function that joins multiple arrays into one. 
    4. Finally, within our “concat()” we make a recursive call to our “customMap()” with the remainder of the “ittClone” and the original function to apply.
This has the effect of going through the iterable variable one at a time, applying the provided function, and constructing a final array to return without looping!

Types in JS Functions