Trying to solve "Historical Life Expectancy" problem on http://eloquentjavascript.net/05_higher_order.html.
The solution from http://eloquentjavascript.net/code/#5.3 looks like:
function average(array) {
function plus(a, b) { return a + b; }
return array.reduce(plus) / array.length;
}
function groupBy(array, groupOf) {
var groups = {};
array.forEach(function(element) {
if (groupOf(element) in groups)
groups[groupOf(element)].push(element);
else
groups[groupOf(element)] = [element];
});
return groups;
}
var byCentury = groupBy(ancestry, function(person) {
return Math.ceil(person.died / 100);
});
for (var century in byCentury) {
var ages = byCentury[century].map(function(person) {
return person.died - person.born;
});
console.log(century + ": " + average(ages));
}
// → 16: 43.5
// 17: 51.2
// 18: 52.8
// 19: 54.8
// 20: 84.7
// 21: 94
My question is around groupOf(element). What's going on here? "element" takes a value of 16,17,18,19,20 or 21 (as a result of function(person) {return Math.ceil(person.died / 100);}). a) What does groupOf(element) look like? groupOf was never defined. b) It seemed to me that I could substitute groupOf(element) with element but that's not true... Can someone help me understand what I'm not understanding? Thanks.
-
If groupOf = function(person) { return Math.ceil(person.died / 100);}, then element = person?user3164317– user31643172015年05月06日 16:34:50 +00:00Commented May 6, 2015 at 16:34
2 Answers 2
groupOf is defined. Its a parameter in var byCentury = groupBy(ancestry, /* function goes here */);
It's a bit difficult to see because of all the brackets. It's the same as doing:
var myFunctionAsAParameter = function(person) {
return Math.ceil(person.died / 100);
}
Then...
var byCentury = groupBy(ancestry, myFunctionAsAParameter);
myFunctionAsAParameter does not execute until the JavaScript sees it with (), which you see happening in: groups[groupOf(element)].push(element);
So in this case, it will get executed a few times, each time with different person (determined by the foreach loop).
It IS a bit of a struggle to wrap your head around, but it's pretty powerful. Functions can take other functions as parameters. They'll only get executed when you add the (). Functions can also return other functions if they want. Now to really hurt your head. Functions can even return and accept themselves as parameters (known as recursion).
1 Comment
if you look closely at this snippet in your code
var byCentury = groupBy(ancestry, function(person) { // element = function(person) {return Math.ceil(person.died / 100);}
return Math.ceil(person.died / 100);
});
groupOf is nothing but this function which is passed as a second parameter to groupBy
function(person) { // element = function(person) {return Math.ceil(person.died / 100);}
return Math.ceil(person.died / 100);
}
since functions are just objects in javascript, you can pass them around to other functions as well.