Partial Application - Eloquent Javascript

风流意气都作罢 提交于 2019-12-21 20:26:47

问题


I am reading Eloquent Javascript and am having a difficult time understand the example below. Would anyone be able to do a line by line type explanation? Specifically, I'm confused as to why the first loop is starting at one, and why the push method is being used on both knownArgs and arguments. I know that this is related to "partial application", but would like a more detailed explanation of what exactly is happening line by line.

var op = {
 "+": function(a,b){return a + b;}
};

function partial(func) {
 var knownArgs = arguments;

 return function() {
  var realArgs = [];

  for (var i=1; i<knownArgs.length; i++)
   realArgs.push(knownArgs[i]);

  for (var i=0; i<arguments.length; i++)
   realArgs.push(arguments[i]);

  return func.apply(null, realArgs);
 };
}

map(partial(op["+"], 1), [0, 2, 4, 6, 8, 10]);

回答1:


The knownArgs variable keeps a copy of the value of arguments as it was when partial() was called. That call returns another function, and inside that code arguments are a whole different list — they're the arguments passed to that returned function. In other words:

var p = partial(someFunction, "hello", "world");

When p() is called, knownArgs will be "hello" and "world" (well and someFunction too but note that the first loop starts at 1). If the call to p() looks like this:

p("how", "are", "you");

then it will first push "hello" and "world" onto the realArgs list (from knownArgs), and then the three parameters passed to p(), from arguments.

edit — step-by-step breakdown of how map(partial(op["+"], 1), [0, 2, 4, 6, 8, 10]); is evaluated:

  1. First, op["+"] has to be evaluated. I'm guessing it returns a function, probably something like this:

    function add(a, b) {
      return a + b;
    }
    
  2. That "add" function and the value 1 are passed to partial(). Thus inside partial() the arguments pseudo-array looks like

    [ add, 1 ]
    

    That is, the first parameter is the "add" function from op["+"] and the second is that value 1. The only thing that partial() really does before returning the anonymous function is to save arguments into knownArgs. That has to be done because the weird arguments pseudo-variable is always assigned a new value upon each and every function call. It's being preserved here so that the code in the anonymous function can access it later.

  3. Now, with the anonymous function returned from partial() and that array of even numbers, we call map(). That function probably looks something like this (I don't have the book):

    function map(fn, list) {
      var i, result = [];
      for (i = 0; i < list.length; ++i) {
        result.push( fn( list[i] ) );
      }
      return result;
    }
    

    Inside map(), then, the first parameter is the anonymous function returned from the earlier call to partial(). What does that function do? Well, it combines the parameters from the original partial() call — except the first one — with the parameters passed into it. The map() function only passes one parameter, so the resulting parameter list on each call to the anonymous function will be the value 1 passed to partial() and then, on each iteration, a different even number from the list.

A simpler example would be to consider what happens when you call:

partial(op["+"], 1)(2);

That is, if you call partial() and then immediately use its return value (the anonymous function). The effect will be the same as calling:

add(1, 2);



回答2:


The first loop starts at one instead of zero because knownArgs[0] contains the function, not its argument.

push appends a single element to an array. It's a fairly common way to build an array.

  var realArgs = [];

  for (var i=1; i<knownArgs.length; i++)
    realArgs.push(knownArgs[i]);

  for (var i=0; i<arguments.length; i++)
    realArgs.push(arguments[i]);

will create a new array concatenated from knownArgs and arguments. knownArgs holds the curried arguments and the function (which is not appended to realArgs), and arguments are the arguments supplied to the function when it's being called.



来源:https://stackoverflow.com/questions/13335600/partial-application-eloquent-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!