Higher order functions - Javascript

前端 未结 2 1652
清歌不尽
清歌不尽 2021-01-22 10:21

I am working through Eloquent Javascript. The function count takes an array and a test function (equals(x)) as arguments, and returns the amount of elements in

相关标签:
2条回答
  • 2021-01-22 11:10

    The 3 arguments you passed to reduce were:

    {
        combine:function(total, element){...},
        base:0,
        array:array
    }
    

    The function then takes base and passes it to the combine function as the total argument:

    base = combine(base, element);
    

    Basically, what is happening here is that for each element in the array you just passed (as the 3rd argument array) the function takes the argument base and increments it using the anonymous function you have provided (which first checks if the element passes test). Finally, after it has iterated over all the elements, it returns the final value of base.

    Perhaps this will help explain:

    function count(test, testarray) {
      var anon = function(total, element) { // Where is the value for total coming from?
        return total + (test(element) ? 1 : 0);
      };
      //now anon is a function.
      return reduce(anon, 0, testarray);
    }
    

    Let us look at the function invocation and definition closely:

    return   reduce(anon   , 0   , testarray);
                      |      |     |
                      v      v     v
    function reduce(combine, base, array) {
        combine;    //the function that is passed in as the first argument
        base;       //the number that is passed in as the second argument
        array;      //the array that is passed in as the third argument
    

    The values of each of anon,0, and testarray, get passed into the function. Within the function, their values can be accessed by the parameter names in the function definition.

    0 讨论(0)
  • 2021-01-22 11:18

    I see that reduce is being passed an anonymous function rather than the combine function

    That is not really true. The anonymous function is the combine function.

    combine(base, element) vs function(total, element)

    these two function calls essentially equal to each other: combine(base,element) and function(total,element)?

    No, they're completely different things.

    The former a function call, to a function referenced by combine.
    The second, however, evaluates to a new function value. In the case of:

    reduce(function(total, element) {...}, ...);
    

    reduce() is being passed a function value, what this means is, that a new function is created, a function that accepts two parameters (denoted by total and element). This function is then passed to reduce.


    Let me recycle my visualization from yesterday. It is important to realize, that this does not only apply to your case, but it applies to every embodiment of the reduce(left) concept.

                       return value of reduce()
                       /
                     etc ...
                    /
                combine    
               /       \
           combine      xs[2]
          /       \
      combine      xs[1]
     /       \
    0         xs[0]
    

    Of course, this only shows what happens, not the how and I think in your case you're asking for how. Just keep this visualization in mind to see what the result is going to do.

    Substituting functions

    To make it more clear what is going on, I'm going to gradually substitute the functions that are being passed around.

    Start of the program:

    function countZeroes(array) {
      return count(equals(0), array);
    }
    

    equals(0) (you could call this a form of currying) evaluates to a function, that is being passed to count().

    This results in basically the following count() function:

    function count(array) {
      return reduce(function(total, element) { // Where is the value for total coming from?
        return total + (0 == element ? 1 : 0);
      }, 0, array);
    }
    

    From here, we can extract the combine argument:

    function combine(total, element) { // Where is the value for total coming from?
        return total + (0 == element ? 1 : 0);
    }
    

    That is the function, that is used within the reduce function:

    function reduce(base = 0, array) {
      forEach(array, function (element) {
        base = combine(base, element);
      });
      return base;
    }
    

    reduce(0, array) is called from the count() function. The function that is passed to forEach could now be rewritten like this, taking into our account implementation of combine:

    function reduce(base = 0, array) {
      forEach(array, function (element) {
        base = base + (0 == element ? 1 : 0);
      });
      return base;
    }
    

    Keep in mind, that base represents our total.

    As our final step, we take into account what forEach() does.

    function reduce(base = 0, array) {
      for (var i = 0; i < array.length; i++)
        base = base + (0 == array[i] ? 1 : 0);
      }
      return base;
    }
    

    So this is what count() essentially looks like, all calls unwrapped:

    function count(array) {
      var base = 0;
      for (var i = 0; i < array.length; i++)
        base = base + (0 == array[i] ? 1 : 0);
      }
      return base;
    }
    
    0 讨论(0)
提交回复
热议问题