I know there are many threads for recursion here. And technically I do understand the principle behind recursion, I'm just more of curious as to where the actual recursion counter is stored or how does the compiler keep track of it
This is probably better understood by code. I have created a simple recursion function in javascript.
function factorial(number){
if (number > 1) {
return number * factorial(number - 1);
} else {
return number;
}
}
Now, everybody understands how this works. We call a recursive function on the factorial which repeats recursively until a function end.
My question would be, how come the factorial function stops executing the recursion at the correct time? If we tried to debug the function in our mind, my understanding is, it would look something like this:
Let's say we called factorial(3);
Function Invoked -> Load Arguments
Calculcate the IF condition -> 3 > 1 -> apply recursive function
3 * recursive(2) * recursive(1) => 3 * 2 * 1 = 6
Now my question is, how is that possible? How come a) if we reduced the recursive counter to 1, we didn't enter the else { statement given it should be evaluated as false, and b) how come the recursive counter knew, to loop the recursive function only number-Nth amount of times?
For better illustration, I added the following line of code
document.write("entered with number " + number + "</br>"); so we'll print it out every time we enter the if condition.
function factorial(number){
if (number > 1) {
document.write("entered with number " + number + "</br>");
return number * factorial(number - 1);
} else {
return number;
}
}
document.write(factorial(3) + "<br/>");
As you can see, the if condition if condition evaluated as true and printed out the message for 3 and 2. How come the counter didn't loop lower and how come we never returned to the initial else { return number; } if we called the recursive operation on factorial(2-1)?
It is pretty difficult question to word, so if you have any idea on how to formulate it better, feel free to edit my question!
Here's a verbal description of what the recursion is doing, in too much detail:
You call factorial(3) in your document.write().
factorial(3) wants to return 3 * factorial(2). Before it can return a value, it has to work out what factorial(2) means.
So now we have that factorial(3) waiting for the results of factorial(2). factorial(2) runs, and wants to return 2 * factorial(1). Before it can return a value it has to work out what factorial(1) means.
Now we have factorial(3) waiting for the results of factorial(2), which is waiting for the results of factorial(1). factorial(1) runs, and sees that its input is 1, so hits the "else" block, so just returns 1 to its caller, the factorial(2).
Now the factorial(2) has what it needs, so can return 2 * 1 to its caller, the factorial(3).
Now the factorial(3) has what it needs, so can return 3 * 2 to its caller.
The calling document.write receives "6".
The recursion "knows" where to stop because eventually it reaches a point where it just returns the number 1, instead of returning something that depends on another call to factorial(). If the function always tried to call itself, there'd be no way out of the recursion loop; it would just keep going until the stack overflows.
Except for factorial(1), every call to factorial(n) will end up calling factorial(n-1) -- so note that factorial(0) or factorial(-1) or factorial(1.01) will never wind up reaching 1, so the recursion will just keep running until the stack overflows. When writing recursive functions, it's a good idea to watch for and handle input that will never reach an exit point; in this case you'd want to throw an error if the input is anything other than a positive integer.
How come the counter didn't loop lower and how come we never returned to the initial else { return number; } if we called the recursive operation on factorial(2-1)?
It did, but your document.write inside the function was inside the if block so nothing was printed when the function went into the else block instead. Here's a more verbose version of the same function, which may give you a clearer picture of what happened:
function factorial(number) {
document.write("entered with number " + number + "<br>");
if (number > 1) {
document.write("recursing<br>")
return number * factorial(number - 1);
} else {
document.write("Returning 1<br>")
return number;
}
}
document.write(factorial(3) + "<br>");
what exactly determines when does recursion stop? When the recursion of the function returns the same result twice (in this case 1?) or is there some different trigger?
Try not to think of this in terms of there being a "counter" of some sort keeping track of when the function should stop recursing, or a "trigger" that actively stops it -- that's a misleading way to look at it. Each instance of the function knows only what input it received, and what it wants to return. Most of the time what it wants to return happens to include a call to the same function, that's where the recursion comes from; when what it wants to return doesn't involve a function call, the recursion comes to an end.
For this particular function, for any input other than 1, it calls a new instance of itself with input n-1 (and waits for the results before it can return to its parent caller), so the recursion continues. For input of 1, it doesn't call itself, so the recursion ends. That 'else' block is your "trigger" (though, again, that's a misleading way to think of it; it's not "triggering" anything, it's just returning a number instead of calling a function to return its results.)
f(3) calls f(2) which calls f(1) which doesn't call anything. If you edited the function to call itself with n+1 instead of n-1, then f(3) would call f(4) which would call f(5) and so on until you run out of memory.
Related
I am new learning the fundamentals. I have looked at many questions on here and youtube, and even on my udemy lecture. But none answer my question.
To be clear, my question is NOT how to use the return operator. I can use it perfectly well. The question is more to do with HOW it works, and what is actually happening in detail.
And please don't say "So in short, when we return something from a function, we are actually returning it from a function." - because this was one of the explainations I got before, and it does not explain anything to me hahaha :)
Here is the example code for this question:
function example(digit1, digit2) {
const sum = digit1 + digit2;
return `${sum}`
}
const invoke = example(1, 2);
console.log(invoke);
I think the best way to answer this question is to give me a step by step list of the journey that 'sum' makes. From the moment it is written, to the end of the whole code.
The return operator is clearly moving 'sum', as the word 'return' can only mean this, by definition.
When I read this code I see that 'sum' is inside the curly braces off the function, and then directly after this 'sum' is then RETURNED (to the place which it started). Now as 'sum' has not gone anywhere, returning it (to the place which it started) is REDUNDANT.
when the function is invoked there must be some kind of journey happening which I do not understand.
Thank you for your time :)
When I read this code I see that 'sum' is inside the curly braces off the function, and then directly after this 'sum' is then RETURNED (to the place which it started). Now as 'sum' has not gone anywhere, returning it (to the place which it started) is REDUNDANT.
Nope. You're misinterpreting what's "returning" and where it's being returned to.
The function is returning the value contained in sum to whatever called the function, not to "the place where it (sum) started".
function example(digit1, digit2) {
const sum = digit1 + digit2;
return `${sum}`
}
const invoke = example(1, 2);
console.log(invoke);
The function example receives two values which it places in the variables digit1 and digit2, then creates a new variable sum which contains the result of adding digit1 and digit2. (The variables digit1, digit2, and sum are all scoped to the function itself; they do not exist outside of that function.) It then returns the value contained in sum -- not the variable itself -- to the thing that called the function.
Which in this case, is this line:
const invoke = example(1, 2)
The function example receives the values 1 and 2, and returns the value "3". Which means that outside the function, the returned value takes the place of the function call itself, resulting in, effectively,
const invoke = "3"
The code outside the function "calls" the function. The function "returns" a value -- not a variable, a value! -- to the code outside the function. You can think of a function as a box with inputs and an output: you call it with inputs, and it returns to you an output value.
(Incidentally, the return statement you've used unnecessarily coerces the result into a string, where you probably want a number: just return sum would likely be preferable.)
return will put whats being returned (sum in this case) at the place where the function is invoked (in this case, in front of invoke).
so invoke = sum (sum is returned/ put on the place where the function is invoked)
I have been looking at this code and scratching my head at it for too long and was hoping to gain insight into how exactly the value 33 is the end result.
I know that this code goes through the conditionals to the else and decrements the value of b until it reaches the else if conditional where the b ==1 condition is met.
What I don't understand, is how within that else if, the value of b is incremented and from then on, so too does the value of 'a' until the final value of 33 is reached.
The other strange feature of this code is that after the else if has made those changes, only the else runs and the other conditionals are no longer checked.
For someone relatively new to recursion, this behavior is truly weird.
function mlt(a, b) {
debugger;
if(!(a && b)) {
return 0;
} else if (b == 1) {
return a;
} else {
return (a + mlt(a, b - 1));
}
}
console.log(mlt(3, 11));
Copying this in the browser console and running through the loops will give insight into what I am on about.
This is not an example of closure, but of recursion.
In order to understand how recursion can bring the correct result, it can help to assume for a moment that the recursive call returns the correct result and see if that makes the overall return value correct as well.
Let's take for example this main call:
mlt(20, 4)
The execution will go to the else part and perform the recursive call:
return (a + mlt(a, b - 1));
As you can derive, the recursive call comes down to mlt(20, 3). Now let's just for a moment assume that this recursive call returns the correct result, i.e. 60. See what happens in the above expression:
return (20 + 60);
This is 80, which indeed is the correct result for our original call mlt(20, 4). So we can get a feel of how this function will return the correct product for any given b if we can assume the function does it right for b-1 also.
What happens when b = 1? Then the function returns a. We can also see that this is correct. So with the previous conclusion we now can be sure that if b >= 1 the result will be correct.
Note that the function will also do it right for b = 0 as then the first if kicks in. Also note that this function does not cope well with negative values of b: in that case the function will keep recurring with b-1 and will eventually bump into a stack capacity error.
After digging around online, I found a great article which explains recursion in JS clearly for those new to the topic.
The explanations and code examples helped me with getting a better understanding.
In short, this code will plus 3, 11 times which equals 33. We reach the second conditional when 1 is subtracted by 1. Then an anonymous function returns a 11 times.
I hope it helps someone else who stumbles on this issue too.
I have an assignment to count repeated strings base on a Heap's Algorithm Permutation.The first thing I want to do is output the swapped strings, I found this code from jake's answer Can someone please help me understand recursion within this code in a loop? The output of this function are swapped strings.
function permAlone(string) {
var arr = string.split(''), // Turns the input string into a letter array.
permutations = []; // results
function swap(a, b) {
debugger; // This function will simply swap positions a and b inside the input array.
var tmp = arr[a];
arr[a] = arr[b];
arr[b] = tmp;
}
function gen(n) {
debugger;
if (n === 1) {
var x =arr.join('');
permutations.push(x);
} else {
for (var i = 0; i != n; i++) { // how does this loop executes within the call stack?
gen(n - 1);
debugger;
swap(n % 2 ? 0 : i, n - 1); // i don't understand this part. i understand the swap function, but I don't get how indexes are swapped here
}
}
}
gen(arr.length);
return permutations;
}
permAlone('xyz'); // output -> ["xyz","yxz","zxy","xzy","yzx","zyx"]
I have been experimenting it on debugger but still can't get what's happening.
I'm not sure what you mean by
understand recursion within this code in a loop
If you mean you want to see the algorithm in a loop form rather than a recursion version you can see them one by side in pseudocode in the wikipedia page here.
For your questions within the code:
how does this loop executes within the call stack?
You are right to refer to the call stack, and this is a general question regarding recursion. If you don't understand how recursion works with the stack you can refer to this really nice and simple video that demonstrates recursive calls using factorial calculation in java (start around min 4:00).
The line you look at is no different than any other line in the recursive function. We start by defining i and assigning the value 0 to it. We continue to check if it satisfies the condition of the for loop. If it does we step into the loop and execute the first line inside the loop which is the recursive call. Inside the recursive call we have a new stack frame which has no knowledge of the i variable we defined before executing the recursive call, because it is a local variable. So when we get to the loop in the new call we define a new variable i, assigning it 0 at first and incrementing it as the loop repeats in this stack frame/call instance. When this call finishes we delete the stack frame and resume to the previous stack frame (the one we started with) where i=0 still, and we continue to the next line.
All the calls have access to the arr and permutations variables since the function is defined in the same scope as the variables (inside the function permAlone) so within each call - no matter what the stack frame we are in, the changes made to those are made to the same instances. That's why every push done to permutations adds to the existing results and will be there when the function returns the variable at the end.
i don't understand this part. i understand the swap function, but I don't get how indexes are swapped here
Indexes are not swapped here. It is merely a call for the swap function with the correct indices.
swap(n % 2 ? 0 : i, n - 1);
is just
swap(a, b);
with
a = n% 2 ? 0 : i;
b = n - 1;
If the a part is what confuses you, then this is a use of the ternary operator for conditional value. That is, it's symbols used to form an expression that is evaluated differently according to the circumstances. The use is by
<<i>boolean epression</i>> ? <<i>value-if-true</i>> : <<i>value-if-false</i>>
to evaluate the above, first <boolean expression> is evaluated. If it's value it true then the whole expression is evaluated as <value-if-true>. Otherwise, the whole expression is evaluated as <value-if-false>.
In the code itself, for a, n % 2 is the boolean expression - js divides n by 2 and takes the remainder. The remainder is either 1 or 0. js implicitly converts those to true and false respectively. So if n is odd we get
a = 0
and if it's even we get
a = i
as the algorithm requires.
I wrote a function yesterday to count the number of "a" characters in a string. My teacher told me to refactor the code into a recursive function and I don't really know how to do so.
I would like some feedback on the subject, and by the way I'm an absolute beginner in JavaScript.
function numberOfA(n){
var numberA =0;
for (i=0; i<=n.length; i++){
if(n.charAt(i)== "a" ){
numberA++;}
}
return numberA;
}
to call the function following piece of code :
var n = prompt("type a word");
var output = numberOfA(n);
alert (output);
Thanks in advance !
The goal of recursion is to make a function which calls itself.
You might have mutual-recursion -- function A calls function B, calls function A... but that's certainly not needed here, and is better suited for when you know that you need to do two distinct things (one per function) and know that you need to do them in a leapfrog pattern.
Where recursion comes into play is when you're thinking about loops.
Normally, when you're doing things with loops, you might end up having two or three loops inside of one another.
Instead of worrying about managing loops, recursion is a way of thinking about what happens in a single-iteration of a loop, and writing ONLY the code needed to do that.
A really simple example of singular recursion might be to log all elements of an array to the console.
This is not a practical example -- it's a trivial example which has most of the pieces you need to make practical examples.
var array = [ "one", "two", "three", "four" ];
function listNextItem (array, index) {
var item = array[index];
if (!item) { return; }
console.log(item);
listNextItem(array, index + 1);
}
listNextItem(array, 0);
I've created a very simple function which looks like the inside of your innermost loop.
It sets an item variable, based on array[index].
If it doesn't exist, we're done, and we can return out of the function, so we don't try to go on forever (this is very important in recursion).
If it does exist, we log the item's value.
Then we call the exact same function, and pass it the exact-same array, but we pass it the value of index + 1.
Did this change anybody's life, or make loops obsolete?
Not really.
But it's the first step to getting recursion.
The next step is getting a return from recursion.
function recursiveAddOne (current, max) {
if (current === max) { return current; }
return 1 + recursiveAddOne(current + 1, max);
}
var total = recursiveAddOne(0, 3); // === 3 + 1 + 1 + 1
total; // 6
Normally in my return statement, I'd be sending the answer back to the variable in the outside world.
I'm still doing that, but here I'm adding a call to the same function, as part of my return.
What does that do?
Well, the outside function can't return a value until the inside function returns.
The inside function can't return a value until ITS inside function returns...
...and it goes all the way down until my termination-condition is met.
That condition returns a value to its outer function. That outer function returns that added value to ITS outer function... ...all the way up to where the outermost function gets handed the value of all of the other functions put together, and then returns THAT to the outside world.
It's like giving each Russian Matryoshka ("babushka") doll a piece of work.
You start with the biggest one, and go all the way inside to the tiniest one.
The tiniest one does its work first, and hands it back to the next one, which does its work and hands that back... ...all the way back until you're outside again.
Well, the basic concept of recursion is solving a problem with a smaller version of itself.
You have a function, numberOfA which gives you the length of a string(or maybe substring).
So let's say you have the string "javascript' the first string is at index 2.
It's logical to say that the number of as in your string is equal to 1 plus the number of as in the entire substring after the first a.
So what you do, is you add 1 to the number of as in the substring vascript
So here's some psudocode
function numA(str)
{
var substring = substr(index_of_first_a, str.length - index_of_first_a
return 1 + numA(substring);
}
function numberOfA(n, count){
if(!n.length) {
return count;
}
if(n.charAt(i)== "a") {
++count;
}
return numberOfA(n.substr(1), count);
}
var numberA = numberOfA('asdfafeaa', 0);
Try this:
function numberOfA(n) {
return n == "" ? 0 : (n.charAt(0) == "a" ? 1 : 0) + numberOfA(n.substring(1))
}
Here's how it works:
If n is the empty string, return 0 and finish the recursion. This is the base case of the recursion.
Else if the character at the first position in the string is an "a" add one, if not add zero and either way advance the recursion by removing the first character from the string. This is the recursive step of the recursion.
As you can see, every recursive solution must have at least a base case and a recursive step.
<!DOCTYPE html><html lang="en"><body><script>
var foo = function foo() {
console.log(arguments.callee); // logs foo()
// callee could be used to invoke recursively the foo function (e.g. arguments.callee())
}();
</script></body></html>
arguments.callee function will call the currently being executed method.
I am making some modules in Node.js and wondered: "Is there a convention for when to use return statements in Node.js?".
From what I understand return statements should be avoided since they would make the process a blocking operation, but is there a guideline to when they should be used, and when one should stick to callbacks?
Whether something is "Blocking" or not is up to you -- does it take much time?
Any IO operation should be considered blocking, as it relies on something outside the script (which could take any amount of time).
If your own script were to say, loop over something a couple hundred times (And you know this to take more than a fraction of a second) you might consider it blocking.
If a method is blocking, it should accept a 'callback' parameter, and
call that asynchronously.
If a method is non-blocking, it should not
accept a 'callback' paramater, and should have at least one 'return'
statement.
Your convention should simply be that you know a function is asynchronous because it accepts a callback.
If it's a "cheap" operation, that's perfectly fine. Any operations which are performed multiple times where you're not doing CPU-intensive operations can (and often should) be refactored into a "normal" function. This is fine:
function add(x, y) { return x + y; }
This is not:
function fib(n) {
if (n <= 1) return 1;
// this may take a long time if n is large
return fib(n - 1) + fib (n - 2);
}
A possible implementation of fib would take a function to return the result as a parameter, and spread the calculation over multiple calls. Something like the code below, from the book "Node Web Development":
function fib(n, done) {
if (n <= 1) {
done(1);
} else {
process.nextTick(function() {
fib(n - 1, function(val1) {
process.nextTick(function() {
fib(n - 2, function(val2) {
done(val1 + val2);
});
});
});
});
}
}
Where the thread wouldn't be blocked for long.
Yes, a better alternative would be to implement fibonacci in the iterative way, not the recursive one. But this is just to demonstrate how one could "split" a CPU-heavy function.