Not understanding Reduce()

During the Sum All Primes challenge, I ran into an issue that I don’t understand.

function sumPrimes(num) {
  if (num == 0){
  return []
}

const total= [num].concat(sumPrimes(num-1))

I console .log (total) and it prints [10,9,8,7,6,5,4,3,2,1]

after that I use :

return total.reduce((sum,number,index) => {
  if (number <= 3) {
 sum += number ;
}
return sum;
},0);}

console.log(sumPrimes(10));

when I use that total.reduce(). it results in 0. but if i use [10,9,8,7,6,5,4,3,2,1] it prints 6, which is what I thought it would print for total since that is what the console.log for total showed earlier.

can someone explain why this is happening?

  **Your browser information:**

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36

Challenge: Sum All Primes

Link to the challenge:

Do you mean you’re literally doing this;

function sumPrimes(num) {
  if (num == 0){
    return []
  }

  const total = [num].concat(sumPrimes(num-1))
 
  return total.reduce((sum,number,index, t) => {
  	  console.log(sum, number, t)
    if (number <= 3) {
     sum += number ;
    }
    return sum;
  },0);
}

Because this cannot work.

This, on its own (a recursive function to create an array of numbers from num, down to 0), works:

function sumPrimes(num) {
  if (num == 0){
    return []
  }

  return [num].concat(sumPrimes(num-1))
}

But that reduce, you’re trying to generate a completely different thing there, the logic just doesn’t fit at all. That whole function has to run to completion every time, so that reduce operation is going to run every time it recurses and you’re just going to get bizarre results. If you log what total is for each run, you get

[ 1 ]
[ 2, 1 ]
[ 3, 3 ]
[ 4, 6 ]
[ 5, 0 ]
[ 6, 0 ]
[ 7, 0 ]
[ 8, 0 ]
[ 9, 0 ]
[ 10, 0 ]

And as it’s only going to care about the last one in the final pass, giving [10, 0] to your reduce returns 0.

If you add logging at every step, you can see what it’s doing. It cannot work. If you are going to use recursion (and I would strongly advise against doing that in this case, it’s a very bad tactic when massive amounts of calculation need to be done, JS will just fall over) then reduce the result, you need to actually produce the result first (in one function) then run the reduce on the result of that.

1 Like

Okay. thanks. I figured something like that was happening. How would I separate the reduce from the recursion? or maybe just a link to whatever concept it is I’m missing that makes the reduce occur wit the recursion? If you could point me in the right direction that would be great. I appreciate your help.

You absolutely should not use any recursion on this challenge. It is the slowest approach.

Just a separate function

const someArray = myRecursiveFunc(10)

const someValue = someArray.reduce(...)

At the minute you’re running that reduce over and over again with different values; literally all you’re doing currently with the recursion is creating a range of numbers, in your code it has nothing to do with taking the range of numbers and producing a value.

But to stress again what @JeremyLT and me have said, recursion is not the way to do this anyway. Even if you get a working solution for small numbers, it’ll fail on larger numbers. There are ways to do it, but they’ll involve memoisation and/or mutual recursion (trampolining), a naïve solution will not work, the test will time out or it will blow the stack.

thanks. I figured out that what I was trying didn’t work pretty early on. I’m not really trying to solve the challenge anymore. I’m really only concerned with what’s happening with the recursion. I just want to know how I would be able to use the array created by the recursion. I keep trying different ways to separate the function but still can’t figure it out. I’ve been reading about closures and nested functions but still don’t understand. I don’t get what I’m missing.

If you are only interested in the recursion, then you should do these challenges

Generally though, I think learners jump too quickly to trying to use recursion. It is very rarely in actual code that you actually want to use recursion.

I get how to do a recursion. I don’t get how to save the result of a recursion in a variable and use it later on.

// Call the recursive function
let result = myRecursiveFunction(someData);
// Use the output
let reduction = result.reduce(myCallback);

Something like this? You can’t really blend the two into the recursive call for the myRecursiveFunction. If the recursive function makes an array, it makes an array. If the recursive function makes a single value, it makes a single value. It can’t do both.

yes. In that case it would do exactly what happened in my original post. it would try to reduce the recursion instead of just the result of the recursion.

So, is it not possible to save just the results of the recursion in a variable and use just the result for the reduce?

In your original post you tried to put the .reduce() inside of the recursive function. This is your problem. You can’t have sumPrimes() make both an array to concat and a single reduced value. Only one type of thing is being returned, a single value.

You can make some strange hacky stuff to try to force the code into working the way you want, but it is fundamentally a bad approach.

Okay. There were multiple things I was confused about but you guys are a lot of help and I really appreciate you answering my questions. Again, I get that its not a good way of coding but I prints what I expect when I write it this way:

function sumPrimes(num) {

  const array = function myRecursiveFunction(x){

     if (x == 0){

    return []

  }

  return [x].concat(myRecursiveFunction(x-1))

  }

  let total = array(num).reduce((sum,number) => {

    if (number <= 3) {

     sum += number ;

    }

    return sum;

  },0);

  return total

}

console.log(sumPrimes(10))

Thanks for all your help and patience with me.

Yeah, this will work, though

this is a pattern I try to dissuade people from. Most of the time when you have an inner function that is recursive, you can write the logic more clearly as a loop.

1 Like