In Eloquent Javascript, the author asks the reader to write a function countZeroes, which takes an array of numbers as its argument and returns the amo
Looking at the code, there is only one possible answer: Since you the function counter is only referenced once when passed to reduce(), reduce must thus provide the arguments to the function.
Here is a visualization of how reduce works. You need to read the diagrom from top to bottom, / and \ denote which parameters (below) are passed to the counter() function above.
return value of reduce()
/
etc ...
/
counter
/ \
counter xs[2]
/ \
counter xs[1]
/ \
0 xs[0]
counter() is initially provided with 0 (after all, the initial total amount of seen zeroes when you haven't processed any elements yet is just zero) and the first element.
That 0 is increased by one if the first element of the array is a zero. The new total after having seen the first element is then returned by counter(0, xs[0]) to the reduce() function. As long as elements are left, it then passes this value as new pending total to the counter() function, along with the next element from your array: xs[1].
This process is repeated as long as there are elements in the array.
function reduce(combine, base, array) {
forEach(array, function (element) {
base = combine(base, element);
});
return base;
}
As can be seen in the illustration, 0 is passed through base to the function initially, along with element, which denotes xs[0] on the first "iteration" within the forEach construct. The resulting value is then written back to base.
As you can see in the visualization, 0 is the left parameter to the function counter(), whose result is then passed as left parameter to counter(). Since base/total acts as the left paramter within the forEach construct, it makes sense to write that value back to base/total, so the previous result will be passed to counter()/combine() again upon the next iteration. The path of /s is the "flow" of base/total.
element comes fromFrom chapter 6 of Eloquent JavaScript, here is the implementation of forEach() (In the comment, I have substituted the call to action with the eventual values.)
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]); // <-- READ AS: base = counter(base, array[i]);
}
action denotes a function, that is called within a simple for loop for every element, while iterating over array.
In your case, this is passed as action to forEach():
function (element) {
base = combine(base, element);
}
It is the anonymous function defined upon each call to reduce(). So element is "really" array[i] once for each iteration of the for.