Solution 4 question

I have a question in solution 4.
Does arr.length stay 4 (length of [1,2,3,4] ) or will it mutate and become 3 ,2 ,1?
It’s not clear to me because it seems to me that the only way i will get an empty array is if the length stays the same through the whole function.

function dropElements(arr, func, i = 0) {
return i < arr.length && !func(arr[i])
?(dropElements(arr.slice(i + 1), func, i))
: arr;
}

// test here
console.log(dropElements([1, 2, 3, 4], function(n) {
return n > 4;
}));



**Your browser information:**

User Agent is: <code>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36</code>.

**Challenge:** Drop it

**Link to the challenge:**
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/drop-it

It’s easy to test:

function dropElements(arr, func, i = 0) {
  console.log(arr.length)
  return i < arr.length && !func(arr[i])
    ? dropElements(arr.slice(i + 1), func, i)
    : arr;
}

dropElements([1, 2, 3, 4], function (n) {
  return n > 4;
})

outputs:

4
3
2
1
0

This is what happens then:

initial parameters [1,2,3,4] , func, i = 0

0 < arr.length TRUE && !func TRUE

new parameter : arr.slice(1) = [2,3,4], func, i = 1

1 < arr.length (TRUE) && !func (TRUE)

new parameter : arr.slice(2) = [3,4] , func, i = 2

2 < arr.length (FALSE!!) && !func (TRUE)

now it returns arr (which is [3,4] because 2 is not less than arr.length

But the function gives an empty array. Which is correct of course. But i don’t understand why.

This is why i thought that array.length had to stay the same.

Where am i thinking wrong?

Right, this is the magic of recursive functions. So, it is going through that array and dropping elements that do not meet the test function. If it encounters an element that meets the test function, then it returns the remaining array.

In the example you have, none of the elements meet the test function so they all get eliminated. What would you expect to happen if you passed it [1, 2, 3, 4, 127]? What would you expect if you sent [1, 2, 3, 4, 127, 1, 2]? Test it out.

Why? It’s hard to explain without understanding how recursion works on a deeper level. I would recommend to check out some videos to understand how recursion and the call stack work. But basically … the first call gets made and it encounters:

return i < arr.length && !func(arr[i])
    ? dropElements(arr.slice(i + 1), func, i)
    : arr;

If the condition is met (which it is for the 4 elements, it wants to return but can’t until it evaluates the function call. So, this function call gets interrupted and a new one gets started. And then a new one… In the end, you have 4 incomplete function calls on the call stack. Finally we reach a case where the array is empty (all the elements have been dropped) or we encounter an element that passes the test. At that point, we return arr. Now that that returns, the previous function call can finish and it returns, allowing the previous call before that to finish and return to the previous call … That is what happens, all those function calls on the call stack unravel until you get to the first function call and then that just returns back to where we originally called the function.

Yes, it’s weird. It takes a while to wrap your head around. It takes time get it. And really, most coders don’t need recursion that much - in 2.5 years as a developer, I’ve only used it once. (But, there may be some jobs that deal with a lot of data structures that need recursion.) It’s still good to know - it’s good for your brain and it can come up on interviews - but also don’t freak out about it. Just work at it and it will gradually make sense.

So i studied a bit more about recursion in functions and i think this is what happens to finally become the solution an empty array.
Correct me if i’m wrong.

/* if statements

0 < arr.length && !func(arr[i]) TRUE

0 < arr.length && ! func(arr[i]) TRUE first recursion where arr is [2,3,4]

0 < arr.length && ! func(arr[i]) TRUE second recursion where arr is [3,4]

0 < arr.length && ! func(arr[i]) TRUE third recursion where arr is [4]

0 < arr.length && ! func(arr[i]) FALSE fourth recursion where arr is empty array

/*

/* callstack:

dropElements(arr.slice(1), function(n){return n>4}, 0)
dropElements(arr.slice(1), function(n){return n>4}, 0)
dropElements(arr.slice(1), function(n){return n>4}, 0)
dropElements(arr.slice(1), function(n){return n>4}, 0)
dropElements([1,2,3,4], function(n){return n>4}, i= 0)

when the if statement is finally “false” it will RETURN the result of every function in the callstack beginning from the last we put in that callstack. So they all return arr now which is an empty array
*/