Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

102
Views
Implement redux compose function but get RangeError

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?

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

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

about 4 years ago · Juan Pablo Isaza Report

0

Rather than trying to combine functions at the time of compose, it seems much easier to combine them at the time the resulting function is called:

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

  return function (...args) {
    let result = funcs .at (-1) (...args)
    for (let i = funcs.length - 2; i > -1; i--) {
      result = funcs [i] (result)
    }
    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

However, again, reduce make for a much cleaner implementation:

const compose = (...fns) => (arg) => 
  fns .reduceRight ((a, fn) => fn (a), arg)

or if you want to allow the rightmost function to receive multiple variables, then

const compose = (...fns) => (...args) => 
  fns .reduceRight ((a, fn) => [fn (...a)], args) [0]
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!