简体   繁体   中英

How Array.reduce put functions as parameters in function composition?

Can somebody explain to me how Array.reduce can put functions as arguments in function composition like this:

const  composeB  = (f, g) =>  x  =>  f(g(x))

const  add = a => b => a  +  b
const  add5 = add(5)
const  double = a => a * 2

const add5ThenDouble  = [double, add5].reduce(composeB)

console.log(add5ThenDouble(6)); // 22

So, according to my knowledge (which is not enough) of reduce function is that Array.reduce iterate through an array like this - it takes each of array values and puts them through callback function with another argument (lets call it accumulator). The next array value will undergo the same callback function, but with (eventually) changed accumulator value.

What confuses me in code example above is:

1) Array is list of functions [double, add5].

2) In first iteration, composeB will receive arguments: f=accumulator (empty value), g=double(function). ComposeB should return emptyvalue(double(6)) (or maybe not??)

I know that I am missing something, but can someone explain me what?

The documentation for reduce says that the first argument is

A function to execute on each element in the array (except for the first, if no initialValue is supplied).

So in this case, you have not supplied an initialValue and so compose is only called once (with arguments double and add5 ).

var inc = (x) => ++x, // increment +1
    x2 = (x) => x*2, // multiply by 2
    sq = (x) => x*x; // square

var compose = (f,g) => (_) => g(f(_));

var f1 = [ sq, inc, inc ].reduce(compose, (_) => _); 
f1(10); // 102

var f2 = [ inc, sq, inc ].reduce(compose, (_) => _); 
f2(10); // 122

See the code above, notice:

  • identity function (_) => _ as default value (second argument) for reduce
  • compose will NOT return a number, it will return a FUNCTION that is a composition of all the functions that were passed in before... So - only when you CALL the (say) f1 , only then the functions will be executed.
  • we are putting all the functions from list [a,b,c,d,e] into a chain of e,d,c,b,a (reverse order!) and then execute as e(d(c(b(a(10))))) getting the order we actually wanted.
  • (f,g) => (_) => g(f(_)) <-- function arguments are actually reversed when calling them. Longer version: function compose (f, g) { return function (z) { return g(f(z)); }; } function compose (f, g) { return function (z) { return g(f(z)); }; }

ps: i use var because i can ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM