javascript - Having trouble stepping through function that reduces an array of functions -
when using reduce method on array of functions having difficulty tracing through how reduce works on array exactly.
combofunc(num, functionsarr) { return functionsarr.reduce(function (last, current) { return current(last); }, input); }
so functionsarr = [add, multi]
, functions add
, multi
being
function add(num) { return num + 1; }
and
function multi(num) { return num * 30; }
the function combofunc
would:
combofunc(2, functionsarr); //returns 90;
i understand how reduce method works on array of numbers folding array 1 value were, applying function each element of array. example combofunc taking array of functions parameter uses simple enough math can understand how reduce produces value of 90 mathematically don't understand happening line line , on each iteration functional level. i'm unable articulate in mind happening when---how input of 2 getting passed function function vis-a-vis closure , sequential firing off of each function, etc.
if reduce method applies function pass in each element of array, , when each element in array function...how can write out own understanding syntactically how looks?
the function passed reduce method returns current(last)
that's function returning function. make last
equal add
function , current
equal multi
? in other words returning multi(add)
? if logic correct, means happening input gets passed add
, computed , returned value passed multi
, computed return 90?
it looks you're trying create composition function takes array of functions apply input, num
let's first cover couple syntax errors. first you're missing function
keyword
// code combofunc(num, functionsarr) { // should function combofunc(num, functionsarr) {
next, you've named parameter num
reference input
in function body
// code }, input); // should }, num);
so after fix this, function works, if approach problem little differently?
disclaimer: answer not walk through function you've provided. rather, sympathizes difficulty demonstrating
combofunc
written in overly complex way. in turn, give alternate definition of function operates identically lot easier read/understand.
to begin, think should go basics of function composition.
i picturing function composition little map.
f(x)=y g(y)=z +--------> y -------+ | | | | | v x ----------------> z ?
in example above, replace f add
function, , g multi
function. defining ? should obvious now.
add(2) multi(3) +--------> 3 -------+ | | | | | v 2 ----------------> 90 h(x) = g(f(x)) = z h(x) = (g∘f)(x) = z h(2) = 90
(g∘f) can said "g of f" , means apply x f first, apply result g.
notice y isn't present. we've defined h in terms of x gives direct "map" z, skipping on y entirely.
composing 2 functions basic operation, , define function easily
function comp(g,f) { return function(x) { return g(f(x)); } } var h = comp(multi,add); h(2); // 90 // h(2) = multi(add(2)) = 90
"yeah, i'm trying work n functions. not 2."
ok, comp
works 2 functions, i've on simplified problem. you're wondering how work if wanted compose 3, 4, or more functions together.
well let's @ again
a(w) = x b(x) = y c(y) = z d(w) = c(b(a(w))) = z d(w) = (c∘b∘a)(w) = z
look closely @ ∘
. know our comp
function , can see appear between each of our functions, a, b, c.
before go further, let's have array of numbers
var xs = [1,2,3];
if want sum numbers, need call
var sum = 1 + 2 + 3
see how +
appears between each number? our array of functions, it's no different!
var fs = [c,b,a]; var d = (c ∘ b ∘ a)
we need make valid javascript. , it'll easy because we've defined ∘
comp
.
this calling of function between terms in list called linear fold , javascript has function called reduce
.
alright, let's put use! we'll fold ("reduce") our list of functions using our comp
function
function compn(fs) { return fs.reduce(comp); } var h = compn([multi, add]); h(2); // 90 // h(2) = multi(add(2)) = 90 // h(2) = (multi ∘ add)(2) = 90
ok, works our original 2 functions, let's make sure works longer list
var = compn([multi, add, add, add]); i(2); // 150 // i(2) = multi(add(add(add(2))) = 150 // i(2) = (multi ∘ add ∘ add ∘ add)(2) = 150
ok, let's recap
function add(num) { return num + 1; } function multi(num) { return num * 30; } function comp(g,f) { return function(x) { return g(f(x)); } } function compn(fs) { return fs.reduce(comp); } compn([multi, add])(2); // 90
"but why better?"
just cut out y
in h(x) = (g∘f)(x) = z
, notice how our compn
function doesn't concern num
, last
, or current
. we've dropped 3 variables our brain think , it's clearer our function doing.
comp
takes f , g , composes them make g ∘ f
.
compn
calls comp
between each term in list of functions
to me, straight forward , easy understand. looking @ function bodies each comp
, compn
, can identify intent immediately.
compare to
combofunc(num, functionsarr) { return functionsarr.reduce(function (last, current) { return current(last); }, input); }
it's no wonder had difficulty trying follow it. combofunc
concerning onset because it's trying 2 operations instead of one.
so, know didn't step through original function, hope after reading answer have greater understanding of function composition , building own functions separated concerns.
edit
according discussion below, valuable our compn
function work on empty array, []
.
var f = compn([]); // uncaught typeerror: reduce of empty array no initial value
yuck! intended behavior here compn
create function returns unmodified input.
function id(x) { return x; }
using starting point reduce guarantee our compn
function work when empty array given
// revised compn function compn(fs) { return fs.reduce(comp, id); }
check out
compn([])(2); // 2 compn([multi, add])(2); // 90
now compn
work array of 0 or more functions.
Comments
Post a Comment