Function call within it's self

Function call within it's self
0

Tell us what’s happening:
Edited query to remove solution to challenge
How is calling a function inside itself working. I can only find complicated examples of uses, but I can’t find a simple explanation for how this works or what it’s doing. I don’t feel comfortable moving on until I can grasp this.

Your code so far

function self(a){
self(1)
}

self(2)

Your browser information:

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

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-algorithm-scripting/factorialize-a-number

I will try to explain it.
At a low level, Stack is used for this kind of recursion.
1st Call:
num is assigned to the value 5
then checked against the if condition, as num = 5, condition fails. So next line is going to be executed which is combination of a function call and some multiplication operation,which is not going to be performed now. Now its like:
5 * factorialize(5-1) = 5* factorialize(4)
at next call ,
4 * factorialize(4-1) = 4 * factorialize(3)
next,
3 * factorialize(3-1) = 3 * factorialize(2)
next
2 * factorialize(2-1) = 2 * factorialize(1)
at next call,
1 * factorialize(1-1) = 1 * factorialize(0)
at next call,
if block is going to be executed as the condition now num === 0 true, and returns 1.
This returned 1 is going to be assigned to the function call which is just called. i.e, now it is assigned to factorialize(0) after the multiplication operation is performed.
1 * 1 = 1. now it is assigned to the function which called it.
So,
2 * factorialize(1) = 2 * 1 =2
3 * factorialize(2) = 3 * 2 =6
4 * factorialize(3) = 4 * 6 = 24
5 * factorialize(4) = 5 * 24 = 120
is the answer.
I think this image may help you to understand clearly:

Hope it helps
All the best

Why use this method? It is extremely inefficient.

Iterating over the factorials and just multiplying the result by the next integer is WAY faster. Not to mention you are actually creating code that is built to fail to essentially be stuck with a value that may or may not be what you intended. Below is the solution removed my solution per moderators request I used, which is extremely fast and you are left with a concise result and an easy to understand code.

You asked for an explanation and the user gave one to you. Whether it is efficient or not was not the question. The recursive solution is more readable than the iterative version, but performance wise, the iterate solution is faster.

Also, can you please avoid posting solutions?

1 Like

You seem to be pretty hostile to my queries. Every time I ask something in these forums you find it necessary to point out that it’s been changed in git or there is an issue with my response, and you don’t even add anything of value.

First off he didn’t even answer my original query “how is calling a function inside itself working?”

Second I don’t see the harm in asking for more information surrounding the information he responded with.

That being said I will remove my solution…

Nothing wrong with replying back with follow up questions, but in terms of hostility, your reply above seemed to accuse the respondent of implying the recursive solution was efficient.

The respondent did make an attempt to answer the question. For most people, recursion is confusing if you have only ever seen iterative solutions. We have created 3 new challenges for the Basic JavaScript section that are devoted to recursion and will show on the site once the master branch has been deployed (keeping fingers crossed that happens in the next couple of weeks). We are hoping these help users better understand the relationship between recursive and iterative solutions.

If I tell you something has changed on the repo (I assume that is what you mean by “git” here), then I am just giving you a heads up. When others find and read the response, the hope is other users will not ask the same question again.

I am sorry you feel my responses are hostile. That is not my intent. If someone states something factually incorrect, it is my duty to point it out so as not to have other users think something is valid when it is not. If you have specific grievances with any responses I have given you, I ask that you send me a DM where we can discuss further in private.

2 Likes

Recursion is one of the concept in programming which is useful in certain conditions. As you said, for this factorialization, iteration could be efficient one But there may be some tasks that are need to be solved by executing the same code with different input values, there comes the use of Recursion. In Algorithm Design strategies like Divide and Conquer, Dynamic Programming, Greedy Method, most problems are solved efficiently by using the concept of Recursion. If we taken care in base condition(i.e, There should be a terminating condition to break the recursion), the concept recursion helps us to solve some complex problems efficiently. Here factorial is just an example of recursion and yes, the solution of iteration is better than recursion in this case. But for Complex problems, Recursion provides readability to the user to better understand how the problem is being solved.

1 Like

Be careful of this - while this is recursion, in its strictest sense, it’s also an infinite loop. Fortunately, FCC and codepen (and other mature online dev environments) catch and short-circuit that, but it’s “infinite nested Russian dolls.”

In order for recursion to be useful, there has to be an end-point. Just as in a for loop or a do-while or whatever mechanism, there needs to be a defined end point.

Is recursion more efficient? In general, not so much. It can be more legible and logical, under certain circumstances, but it all depends on personal preference (or, more accurately, assuming you are working towards a career, your employer’s preference).

In terms of efficiency, if that is a good benchmark, simple iterative loops are faster than higher-order functions ( like .map or .forEach), which are faster than recursion. In general. Individual mileage may vary.

In terms of what it actually does, the key to recursion working well is two things: an end point, and a return value. As the recursive loop gets deeper and deeper, a series of returned values are being stacked, from each recursive step. When that end point is reached, the entire stack of return values is collapsed, by whatever mechanism you specify.

There are ways to simply have the recursive values added, or to have an array or a string built by a recursion, or all sorts of creative ways. What you do with the value being returned from that recursion will determine the final return from the outermost, original, call.

Yeah, recursion is confusing as hell. Every time I think I’ve got a handle on it, I realize it’s slipped on me again. It takes time, and practice, to see any practical use for it. But there are use cases, there are times when it’s the right tool for the job.

1 Like

The Relevant Links part of the challenge guide has a video that starts out with a pretty basic example. I’m not sure if it’s possible to explain how recursion technically works without it getting a bit…well technical.

It is not objectively right or wrong to choose an imperative but faster approach. Measuring the total time gained by faster code over the codes life span can be a bit abstract and hard to measure. However, if the code is more legible that is guaranteed to save real-world time in development, which is usually more important. How well code reads is often more important than how fast it runs.

Code legibility is obviously subjective to some degree, and all code styles and paradigms have their pros and cons. I don’t think recursion is inherently more legible, I personally find that recursive functions can quickly become hard to reason about.

More links


http://hideoushumpbackfreak.com/post/2015/06/28/Recursion-Good-Bad-or-Indifferent

1 Like
function factorialize(num, temp = 1) {
  if (num === 0 || num === 1) return temp

  return factorialize(num - 1, temp * num );
}
factorialize(100);

简单来说js闭包原则,当有函数内部变量有外部引用时候不能释放,故会产生内存泄漏
经常我们的做法就是尾调优化

1 Like

Thank you this was a great explanation. I’m not an algorithmic programmer (or even a math whiz) so the idea of recursion is a little difficult. I get the idea but still seems odd. I’ll do more research and practice.

Admittedly this is a bit over my head, but if anyone comes across this thread I found some good info in StackOverflow https://stackoverflow.com/questions/310974/what-is-tail-call-optimization

Thank you for this information, it gave me something to research.

This poor example was made because I couldn’t find a simple example of what I was trying to ask (probably because I didn’t understand what I was asking). I love all this information you provided though. Thanks for taking the time to explain this.

1 Like

I’m sorry, I was tired and being too terse. It wasn’t a poor example at all. it was a perfect one, and easy to use to gain understanding. I simply wanted to make sure you understood the pitfall in that particular code. :wink:

… and yes. The above post? That was my version of terse. BWAAHAHAHAHAHA!

1 Like

No,no. You weren’t terse at all (or didn’t come off that way). I Was tired when I wrote that and wasn’t grasping the concept. I’m glad you pointed it out so the next person coming along wasn’t left with a bad idea that was good code.

1 Like

Hi, friend!!

You have to declare a condition to stop the recursion from calling and avoid a stack overflow situation. Recursion is not usually the fastest solution but can help you to avoid repetition and make your code more readable.

For instance, you want to apply the same operation to every number from 5 to 0 and you know that 0! equals 1. You could do (n * (n-1)) until n = 1 with a loop or recursion, a cleaner option for your code.

More info here: https://www.sitepoint.com/recursion-functional-javascript/

1 Like