Recursive flatten function with spread parameters - trouble understanding what's going on

Currently reading through JavaScript Allongé by Reginald Braithwaite, and I came across the following snippet:

const flatten = ([first, ...rest]) => {
  if (first === undefined) {
    return [];
  }
  else if (!Array.isArray(first)) {
    return [first, ...flatten(rest)];
  }
  else {
    return [...flatten(first), ...flatten(rest)];
  }
}

flatten(["foo", [3, 4, []]])
  //=> ["foo",3,4]

The book says to break it down into smaller and smaller steps until I get to a solvable step that will allow me to put the whole thing together, but I just can’t seem to get to that solvable step. Any help would be appreciated. Thanks.

I find it helpful to walk through the steps example input must go through.

Initial call:
flatten([“foo”, [3, 4, []]]);
– Is first undefined?
No.
– Is first NOT an array?
Yes, it is not an array.
– return [ “foo”, …flatten([3, 4, []]) ];

Second call:
flatten([3, 4, []]);
– Is first undefined?
No.
– Is first NOT an array?
Yes, it is not an array.
return [3, …flatten([4, []]) ];

Third call:
flatten([4, []])
– Is first undefined?
No.
– Is first NOT an array?
Yes, it is not an array.
return [4, …flatten([[]]) ];

Fourth call:
flatten([[]])
– Is first undefined?
No.
– Is first NOT an array?
No, it is an array.
return [ …flatten([]), …flatten() ];

In fifth and sixth call, both of these will have “first” equal undefined and hence return an empty array down to the fourth call. The fourth call will then return [ …[], …[] ] to the third call, which will return [4, …[ …[], …[] ]] to second call and so forth. The first call will return the full collapsed array.

2 Likes

Thank you very much, @ArtemPetrov .

I believe the issue was that I didn’t understand the purpose of the ... before each flatten() call. Your answer prompted me to do some rereading, after which I remembered how ... can be used to spread the elements of an array inside another array, which is what collapses the array in the example.

Thanks again. Especially for writing out each step of recursion!