Reputation: 291
var a = [ [1,2,3], [4,5,6], [7,8,9] ];
_.map( a, _.max );
// gives [3, -Infinity, -Infinity]
I have tested it on my Chrome browser, on the lodash site.
Shouldn't the code above return [3, 6, 9]?
I can get the correct result with forEach:
var a = [ [1,2,3], [4,5,6], [7,8,9] ];
var result = [];
_.forEach( a, function(arr) { result.push(_.max(arr)); } );
Upvotes: 3
Views: 2695
Reputation: 29434
I've opened an issue on GitHub: https://github.com/lodash/lodash/issues/379
Thanks to jdalton, the issue is now fixed. Sample: → jsFiddle
I have never worked with Lodash in detail, but here are my researches:
Retrieves the maximum value of a collection. If the collection is empty or falsey
-Infinity
is returned.
— Lodash Documentation: _.max()
Testing _.max()
with each group invidually worked perfectly:
_.max([1,2,3]); // 3
_.max([4,5,6]); // 6
_.max([7,8,9]); // 9
Now, I tried calling _.max()
manually in the callback function of _.map()
:
var a = [ [1,2,3], [4,5,6], [7,8,9] ];
alert(_.map( a, function(val) {
return _.max(val);
}));
Works fine! So where is the difference between that and supplying _.max()
as the second parameter?
_.map()
actually sends 3 parameters to the callback function:
(value, index|key, collection).
— Lodash Documentation: _.map()
Consider the second parameter of _.max()
now:
2.[callback=identity] (Function|Object|string): The function called per iteration. If a property name or object is provided it will be used to create a ".pluck" or ".where" style callback, respectively.
— Lodash Documentation: _.max()
Conclusion: _.max()
gets also passed the second and third parameter supplied by _.map()
. The second parameter is important here! Passing truthy values (e.g. integers != 0) for it lets the function return -Infinity
.
Test cases (→ jsFiddle):
alert(_.max([1,2,3], 0)); // 3
alert(_.max([1,2,3], 1)); // -Infinity
alert(_.max([1,2,3], 2)); // -Infinity
That is coming from the boolean checks performed in the source code: https://github.com/lodash/lodash/blob/f0f7eee963966516490eb11232c9e9b4c6d0cc6c/dist/lodash.js#L3431
Because callback
(the second parameter) is a truthy value, we will directly jump into the else branch. There, callback
is reassigned as the following (the ternary operation will also take the else branch):
lodash.createCallback(callback, thisArg, 3);
createCallback()
is defined here.
It returns the following function for our specific input parameters (these are 1, null, 3
, see _.max()
for details):
return function(object) {
return object[func];
};
Let's say, we save that in a variable called callback
(→ jsFiddle):
var callback = _.createCallback(1, null, 3);
Calling that function with object = 1
(or 2, 3 or 6, etc.) results in undefined
(that's pretty obvious).
Going back to _.max()
, we see that there is a loop which compares the current value (from the callback function) to the initial/last value, and that is -Infinity
as set at the beginning of the function.
undefined > -Infinity
never results in true, so -Infinity
will stay the 'maximum' value.
Upvotes: 5