How does this recursive function for creating a range work?

From this answer to this SO question, this very inventive function creates an array with a range from 1 to i:

function range1(i){return i?range1(i-1).concat(i):[]} 

It works great. Call me stupid, but I just can't figure out how this works. Let say that range1(5) . Now, having entered the function, we have i , so it returns itself with the parameter i-1 (4) and concats i (5). But here I am stuck: how range1 know this is due to an array? I would say that after the first run, the return value (as long as we have i , so i!==0 ) will be Number. And Number does not have a concat method. Can someone explain this? What am I missing?

+6
source share
7 answers

Now, having entered the function, we have i, so it returns itself with the parameter i-1 (4) and concats i (5).

No, he is not coming back. What he does is the call itself, which is recursion, then it returns the result of that call with the last element connected.

So range1(5) will call range1(4) , which will call range1(3) , etc. When it reaches zero, it will stop making calls and just return an empty array.

range1(0) returns [] , so range1(1) returns [].concat(1) , which is [1] , then range1(2) returns [1].concat(2) , which is [1,2] , etc. When we return to range1(5) it returns [1,2,3,4].concat(5) , which is [1,2,3,4,5] .

Note. This function works well for creating small arrays, but if you need a large array, it will be much faster to just create an array and fill it with a regular loop.

+9
source

I have expanded this code because it is easier for me to understand this method.

 function range1(i){ if (i != 0) { return range1(i - 1).concat(i); } else { return []; } 

The logic of this function is that if you need a list of elements 3 ( range(3) ), you take a list of elements 2 ( range1(i - 1) ) and add 3 to the end of this .concat(i) . Besides that, you just need to handle the special case when range1(0) is an empty array [] , and you're done.

Imagine calling range1(2) . Since i != 0 , we obtain

 range(2) = range(1).concat(2) 

range(1) returns range(0).concat(1) , giving us

 range(2) = range(0).concat(1).concat(2) 

Well, what is range(0) ? Since i == 0 , we get an empty array ( [] ), which we need!

 range(2) = [].concat(1).concat(2) -> [1, 2] 
+11
source

The base recursion register is [] , so the recursion tail will return an array, and the remaining steps will be merged with [] (and the previous steps).

+2
source

Take range 1 (4):

 range1(4) => range1(3).concat(4) range1(3) => range1(2).concat(3) range1(2) => range1(1).concat(2) range1(1) => range1(0).concat(1) range1(0) => [] 

Now take the first line and replace range1 (3) with its equivalent from the next line. You will receive the following:

 range1(4) => range1(2).concat(3).concat(4) 

Continue to replace range1 links until they are gone. Final result:

 range1(4) => [].concat(1).concat(2).concat(3).concat(4) 
+2
source

The range1 function always returns an array.

This is either an empty array (for i == 0) or a concatenated array.

0
source

In the base case, range1 returns an empty array that defines concat . Then it unwinds the numbers in the range added to the array.

0
source

until I become 0, nothing happens other than the caling function with the changed value, but when it calls from 0, it returns [] - an empty array that used the concat method in the previous call ... it looks like range (0). concat (1) => [] .concat (1), so [1] returned to the previous call: [1] .concat (2), etc. to start

0
source

Source: https://habr.com/ru/post/890396/


All Articles