javascriptfunctional-programminghigher-order-functions

What's the proper way of passing named functions to Javascript's higher-order functions?


I'm trying to use Javascript's higher-order functions for functional programming. However, they are producing unexpected results:

['1','2','3','4'].map(parseInt) // [1, NaN, NaN, NaN]

['1','2','3','4'].map(function(x){
    return parseInt(x)
}) // [1, 2, 3, 4]

I expected these two calls to Array.prototype.map to both return [1, 2, 3, 4]. How can I map parseInt() without using an anonymous function?

Similarly, I expected the following two expressions to produce the same value:

[4,6,8,3].reduce(Math.max,-Infinity) // NaN

[4,6,8,3].reduce(function(x,y){
    return Math.max(x,y)
},-Infinity) // 8

Also, since I'm new to functional programming in Javascript, please let me know if I'm using any terminology incorrectly.


Solution

  • The problem are those optional arguments - that map and reduce pass to the callbacks, and that parseInt and Math.max unconcernedly accept. See here or there for a more detailed explanation.

    What you basically need to do is fix their arity, so that they take only one resp. two arguments:

    Function.prototype.ofArity = function(n) {
        var fn = this, slice = Array.prototype.slice
        return function() {
            return fn.apply(null, slice.call(arguments, 0, n));
        };
    };
    
    ['1','2','3','4'].map(parseInt.ofArity(1)) // Array [1, 2, 3, 4]
    [4,6,8,3].reduce(Math.max.ofArity(2), -Infinity) // 8
    

    You might also want to take a look at Ramda, where all these methods are designed so that they work like that out of the box.