Note: This is a mult-part series! You're going to benefit the most following it from the very beginning, since we re-use code and concepts from previous posts to build our newer ones.

Back to Basics: Functional Programming

Reduce is quite the monolith. It's a very difficult concept to wrap your head around, and I'll try my best to explain it properly.

The idea behind Reduce is to take an array or object (and, again, like in previous posts, we're going to just optimize for arrays and pretend that objects don't exist), a callback function, and an optional start value.

Reduce will then iterate over the array, continuously mutating that start value to be the result of passing itself and the current element into the callback.

At the very end, Reduce will return a final value, which originally began as a start value.

Let's say that I had an array of numbers:

var numbersArr = [1, 2, 3, 4, 5]

Using reduce, I'd like to sum up all the numbers:

reduce (numbersArr, function(a, b) {  
  return a + b;
}, 0) // returns 15

How does this work? Well, for a complex problem like this let's start with some pseudocode.

function reduce(array, callback, startValue) {  
  // Iterate over the array
    // Check to see if startValue is defined.
      // If startValue is NOT defined, we want to set it to the first element in the array
      // If startValue IS defined, we want to set it to the result of calling our callback and passing in the current startValue as well as the current element we're iterating over.

  // Return the startValue
}

Great, so we want to iterate. Let's continue:

function reduce(array, callback, startValue) {  
  // Iterate over the array
  for (var i = 0; i < array.length; i++) {
    // Check to see if startValue is defined.
    if (!startValue) {
      // If startValue is NOT defined, we want to set it to the first element in the array
      startValue = array[0];
    }
    // If startValue IS defined, we want to set it to the result of calling our callback and passing in the current startValue as well as the current element we're iterating over.
    else {
      startValue = callback(startValue, array[i]);
    }
  }
  // Return the startValue
  return startValue;
}

But wait a minute, startValue = callback(startValue, elem)???? How does that work?

It's all because of Operator Precedence, whic determines the order in which operators are evaluated. This falls under the Assignment category, which states that operations done when assigning values are evaluated in a right-to-left order -- meaning that the code to the right of the = sign is evaluated first, and then the value on the left is assigned its results.

Alright, that's great, but we can do better. Let's keep things DRY and utilize each within this (you do remember each from my earlier posts, right?):

function reduce(array, callback, startValue) {  
  each(array, function(elem) {
    if (!startValue) {
      startValue = elem;
    } else {
      startValue = callback(startValue, elem);
    }
  })

  return startValue;
}

Perfect. We smashed reduce. In our final post, we're going to handle MapReduce. Exciting!