Callback that didn't need parameters - why?

混江龙づ霸主 提交于 2020-02-06 08:40:25

问题


So, I have been working on this 2-part problem and managed to solve it, however I have some questions on how the code actually works - specifically the nature of the callback function. Below are the 2 parts of the problem laid out, along with my solution to both. I was able to solve the first part rather easily, but the second was much more challenging for me.

// FIRST PART OF PROBLEM

var merge = function(array1, array2, callback){  
  //your code here.
}

var x = merge([1, 2, 3, 4], [5, 6, 7, 8], function(a, b){  
  return a + b;
});

//x should now equal [6, 8, 10, 12].


// MY SOLUTION: 
var merge = function(array1, array2, callback){
  var newArray = [];
  
  for (var i = 0; i < array1.length; i++) {
    newArray[i] = callback(array1[i], array2[i]);
  }
  return newArray;
}

var x = merge([1, 2, 3, 4], [5, 6, 7, 8], function(a, b){  
  return a + b;
}); // x equals [6, 8, 10, 12].

Now here is the second part of the problem that I was able to solve, but where I am having trouble is in specifically walking through the code step by step. My question is - why did I not need to give the callback parameter to the merge function any parameters? When I did attempt to provide parameter, x became NaN.

euclidian distance = sqrt((x2-x1)^2 + (y2-y1)^2))."

var euclid = function(coords1, coords2){  
  //Your code here.
  //You should not use any loops and should
  //instead use your original merge function.
}

var x = euclid([1.2, 3.67], [2.0, 4.4]);

//x should now equal approximately 1.08.


// My solution:
var euclid = function(coords1, coords2){
 // // why does function() below require no parameters?
  var merged = merge(coords1, coords2, function() {
    return (coords1[0] - coords2[0]) * (coords1[0] - coords2[0]) +
    (coords1[1] - coords2[1]) * (coords1[1] - coords2[1]);
  });
  
  return Math.sqrt(merged[0]);
};

var x = euclid([1.2, 3.67], [2.0, 4.4]); //x does equal approximately 1.08.

I'm a newbie to programming, so I realize this is probably a rather trivial question. But any help with walking me through how the callback is actually working in this solution would be much appreciated. Thanks!


回答1:


why did I not need to give the callback parameter to the merge function any parameters?

Given:

var euclid = function(coords1, coords2){

  // why does function() below require no parameters?
  var merged = merge(coords1, coords2, function() {
    return (coords1[0] - coords2[0]) * (coords1[0] - coords2[0]) +
    (coords1[1] - coords2[1]) * (coords1[1] - coords2[1]);
  });

  return Math.sqrt(merged[0]);
};

The (callback) function passed to the merge function has a closure to the variables of its outer scope. Including coords1 and coords2 in the formal parameter list of Euclid makes them local variables, so they don't need to be passed to the callback.

If the function was created outside the scope of Euclid, then you'd need to pass them (or reference them some other way).

Incidentally, I prefer function declarations to assignment of expressions, e.g.

function euclid(coords1, coords2) {
  // code here
}

as it makes it more obvious what the function's name is. Consider:

var foo = function fred() {
  // foo or fred in here
};

 // only foo out here



回答2:


The second solution can be said to use merge only trivially. It's like that old question - how do you measure height of a building using an ammeter and a stopwatch? Throw the ammeter from the roof, measure time till pavement.

Your merge function will invoke its callback twice, the callback will calculate the full Euclid distance for the two-size arrays, and it will do it twice (so you'll get [1.08, 1.08] for the result of the merge; then you pick one of the results.

So your merge is a) unnecessary, b) inefficient, and c) doesn't work for any number of elements but 2.


The real solution involves noticing that Euclid distance is a sum; and each element of the sum only involves matching elements from two arrays: a[i] - b[i] squared. That should be your callback; and merge should give you an array like [0.64, 0.53].

The real problem is - how do you sum an array when you can't use loops, only your merge? If you are guaranteed that there will be only two dimensions, it is easy. If not, you will have to cheat.

var euclid = function(aa, bb) {
  var squares = merge(aa, bb, function(a, b) {
    return (a - b) * (a - b);
  });
  return Math.sqrt(squares.reduce(function(a, b) {
    return a + b;
  }));
};

Look, ma, no loops! (At least no overt ones.)


If you really want to only use merge, you will need to cheat harder.

var euclid = function(aa, bb) {
  var sum = 0;
  var squares = merge(aa, bb, function(a, b) {
    sum += (a - b) * (a - b);
    return null;
  });
  return Math.sqrt(sum);
};



回答3:


In my opinion you're getting confused because your callback is not a callback and thus shouldn't be named this way. You rather wanna name it resolver, or calculator: the function one need to provide is not intended to be called back right after the process, but rather to be called while resolving, thus the naming concern. The pattern of providing a calculator function parameter is when you want to give the ability of customizing your function behavior to the caller.

So, the only reason they didn't tell you to make the euclid function accept a resolver parameter is... well, they didn't want you to create a behavior-customizable function. That simple =D



来源:https://stackoverflow.com/questions/32644132/callback-that-didnt-need-parameters-why

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