Home > database >  Implement redux compose function but get RangeError
Implement redux compose function but get RangeError

Time:01-21

I am trying to re-implement redux compose function, instead of using reduce i use a for loop, here is my code:

function compose(...funcs) {
  if (funcs.length === 0) {
    return (arg) => arg;
  }

  if (funcs.length === 1) {
    return funcs[0];
  }

  let result;
  for (let i = funcs.length - 1; i > -1; i--) {
    result = result
      ? (...args) => funcs[i](result(...args))
      : (...args) => funcs[i](...args);
  }

  return result;
}

// test
function fn1(x) {
  return x   1;
}

function fn2(x) {
  return x * 10;
}

function fn3(x) {
  return x - 1;
}

console.log(compose(fn3, fn2, fn1)(10)); // 109

It is expected to log 109 since (10 1) * 10 - 1 is 109, however it gives me such error:

RangeError: Maximum call stack size 

Looks like i am doing some recursion but all i did is just a for loop, no sure where is the problem of my code?

CodePudding user response:

I think the issue is like the below example:

a = () => 2;
a = () => 3 * a();
console.log(a); 
// this prints () => 3 * a() in console
// so when you call a(), it will call 3 * a(), which will again call 3 * a() and so on
// leading to infinite recursion

My solution is slightly different using bind function based on this reference link: https://stackoverflow.com/a/6772648/4688321.

I think bind creates a new copy of the function result and binds it to a new object. Not using bind leads to recursion because then the code becomes like the above example, result calls result.

function compose(...funcs) {
  if (funcs.length === 0) {
    return (arg) => arg;
  }

  if (funcs.length === 1) {
    return funcs[0];
  }

  let result;
  for (let i = funcs.length - 1; i > -1; i--) {
    if (i == funcs.length - 1)
      result = (...args) => funcs[i](...args);
    else {
      let temp = result.bind({});
      result = (...args) => funcs[i](temp(...args));
    }
  }
  return result;
}

// test
function fn1(x) {
  console.log("fn1");
  return x   1;
}

function fn2(x) {
  console.log("fn2");
  return x * 10;
}

function fn3(x) {
  console.log("fn3");
  return x - 1;
}

//console.log(compose(fn3, fn2, fn1));
let ret = compose(fn3, fn2, fn1);
console.log(ret(10)); // 109

  •  Tags:  
  • Related