Eloquent Javascript script character counting example

function reduce(array, combine, start) {
  let current = start;
  for (let element of array) {
    current = combine(current, element);
  }

function characterCount(script) {
return script.ranges.reduce((count, [from, to]) => {
return count + (to - from);
}, 0);
}
console.log(SCRIPTS.reduce((a, b) => {
return characterCount(a) < characterCount(b) ? b : a;
}));
// → {name: "Han", ...}
  return current;
}

I think I’ve mostly figured out how this works (it’s from page 90 of Eloquent Javascript, 3rd edition), but I’m not sure how current in the reduce function gets its first value. The function in the calling function within the console.log doesn’t provide a value for the return function’s start parameter. It seems to me that this may provide an empty value that gets replaced by the first value that its compared against and the program goes on from there, but when I try to provide a null or undefined value directly it causes an error. What is start (and therefore current) when the program begins?

I realized this may not be very clear and can’t seem to edit the original post anymore.

I guess my issue is that

console.log(SCRIPTS.reduce((a, b) => {
return characterCount(a) < characterCount(b) ? b : a;
}));

doesn’t seem to provide the third parameter in the reduce function’s definition, which the reduce function then uses to set up its first comparison.

My understanding is that if you don’t provide a parameter it gets treated as undefined. I’m wondering if, somehow, this undefined parameter is simply treated as empty for the comparison and the program picks the first element of the array as the larger value and goes from there. But when I try to feed the program an undefined value directly, it throws an error saying that it can’t access its properties.

So, again, how does the program get started? What is the initial value of start (and therefore current)?

They are two different code examples.

The first is a standalone function the next two are using the built-in reduce method. You can tell by how they are called as well. The standalone function can not be called on an array as it is not on the prototype, the other two are called on the array so it has to be on the prototype.

If you are just talking about this code.

function reduce(array, combine, start) {
  let current = start;
  for (let element of array) {
    current = combine(current, element);
  }
  return current;
}

console.log(reduce([1, 2, 3, 4], (a, b) => a + b, 0));

If you can look at the reduce call site you can see what is passed to start (0) and if you look at the combine callback definition you can see what it does with the arguments (the result of which is assigned back to current).


Edit: Just to be more clear.

The first reduce function is a custom reduce function written by the author. It is not a method on the prototype and must be passed in the array as an argument to work on it.

The next two reduce examples are the standard JS reduce method. It is a) a method which you can tell by how it is called using a dot .reduce() and b) it is a prototype method which you can tell because it can be called on an array [].reduce().

https://eloquentjavascript.net/05_higher_order.html#h_fx3e34kT/k

Ah, thank you. That makes sense.

I had thought that the latter calls were just an alternate way of calling the custom function, but it does make much more sense that they are referencing a method of the array object.

It also explains what I saw when I tried to look at what was going on with console.log statements. It looked like “current” was element 0 of the array and “element” was element 1, which is how the function (now that I know it’s a standard one I can look up) indicates it works…

Thanks again.

No problem, happy to help.

I personally think it is a slightly confusing way to present the code. I doubt you’re the only one that has gotten tripped up by it.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.