Why counter increases and fn is called? How it works? - javascript

I solved kata on codewars. Acctually I did this by accident and I don't understand why this code works. May you explain it?
Kata:
Write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit.
39 --> 3 (because 39 = 27, 27 = 14, 1*4 = 4 and 4 has only one digit)
My solution:
function persistence(num) {
let count = 0;
const arr = [...num.toString()];
const sumArr = arr.reduce((res, val) => (res *= val));
if (arr.length > 1) {
**// Why? How this line works?
// Why it doesn't crashes?
// Why it returns correct counter value and calls the function?**
count += 1 + persistence(sumArr)
}
return count;
}
persistence(39); //3
Why if I do like this, the counter do not save the result:
if (arr.length > 1) {
count += 1
persistence(sumArr) }

Basically, the persistence(sumArr) function acts as a recursive function and returns count of 0 for a base condition that is when the number is single digit. For 39, count is 1+persistence(27)
For 27, count is 1+persistence(14) and for 14, 1+ persistence (4) which is nothing but 1+0 and recursively it adds up to be 3

count is a local variable, only reachable within the scope of persistence(), so when you do a recursive loop, you create a new variable called count but it's in a new scope - the method that you called - it just happens to have the same name as persistence().
It would be totally different if count were a global variable, outside of the scope of the method.
let count = 0;
function persistence(num) {
...
}
Calling persistence() again within persistence() would then use the same variable, not a new one.

This is recursion!
Whenever a function is called by the caller, that function (a.k.a callee) is pushed into the call stack. All the arguments, local variables needed for that function is present there. This is also known as stack frame. The callee is popped out of the stack when it returns to the caller.
In your case both the caller and the callee happened to be the same function. This is called recursion. During recursion, variables local to that function aren't shared. A new stack frame is set up for each callee.
if (arr.length > 1) {
count += 1
persistence(sumArr)
}
Here, the count that you are returning from the callee isn't getting added up with the count of the caller.
If we visualize what is happening then:
persistence(37) = 1 + persistence(27) = 1 + 1 + 1 + 0 // [putting value returned from persistence(27)]
persistence(27) = 1 + persistence(14) = 1 + 1 + 0 // [putting value returned from persistence(14)]
persistence(14) = 1 + persistence(4) = 1 + 0 // [putting value returned from persistence(4)]
persistence(4) = 0

Related

Can I make an outer argument the same as an inner argument?

I am trying to create a function that returns the sum of all the multiples of 3 or 5 below the number passed in. I immediately recognized the similarity to "FizzBuzz". This is the first codewars challenge. I have created two functions that I have tested and they work independently, but I can't figure out how to reference the argument of the outer function solution() in my inner function returnNumber. Every time I try to run the function, I get an answer of 0.
function solution(number){
function returnNumbers(number){
let numbers=[];
for (let i=1; i<number; i++){
if (i % 3 == 0 && i % 5 == 0) numbers.push(i);
else if (i % 3 == 0) numbers.push(i);
else if (i % 5 == 0) numbers.push(i);
} //end of for loop
return numbers
} //end of returnNumbers
let sum = returnNumbers().reduce(function(a, b){
return a + b;
}, 0);
return sum
} //end of solution
I already tried assigning a new variable for the original argument but maybe I didn't do it correctly. Like this:
function solution(number){
let x = number
function returnNumbers(x){
let numbers=[];
for (let i=1; i<x; i++){
if (i % 3 == 0 && i % 5 == 0) numbers.push(i);
else if (i % 3 == 0) numbers.push(i);
else if (i % 5 == 0) numbers.push(i);
} //end of for loop
return numbers
} //end of returnNumbers
let sum = returnNumbers().reduce(function(a, b){
return a + b;
}, 0);
return sum
}
I imagine the solution is simple, but I am an absolute beginner (< 3weeks) so I would appreciate some help.
The main issue you are facing is scope - how long a variable still "exists". The main thing to realize is that anything in the outer function is still in scope in the inner function, as long as you don't declare a variable with the same name (when you do, the outer variable is shadowed - it still exists, you just can't access it, because when you use that name you'll get the inner one).
So, your first solution is correct, except that you need to not have an argument to the function:
function returnNumbers(number){
should just be
function returnNumbers(){
because number is already in scope, but if you declare it as an argument, you will need to pass it (but that's pointless in this case).
when calling returnNumbers function, argument is not getting passed. Try passing the outer function value to it.
let sum = returnNumbers(number).reduce(function(a, b){
return a + b;
}, 0);
Your inner function already has access to the outer function's parameter (because it's sitting inside of the outer function's brackets). So in your case, returnNumbers can already use number without having it passed as a parameter.
By declaring it as a parameter for returnNumbers, you're shadowing the number variable. You have two possible solutions.
Either pass number to returnNumbers
let sum = returnNumbers(number).reduce(function(a, b){
return a + b;
}, 0);
Or remove returnNumbers parameter
function returnNumbers(){
...
}

Trying to figure out code snippet in the book Eloquent JavaScript

Chapter 3 Functions has the following code snippet:
const power = function(base, exponent) {
let result = 1;
for(let count = 0; count < exponent; count++) {
result *= base;
}
return result;
};
console.log(power(2, 10));
// 1024
can someone explain what is going on in the code line by line, i'm confused by let result = 1 the most. Thanks!
In the first line, you're declaring a variable result. However, it's being declared with let, not var. Let is similar to var, except it can't be accessed outside the block it is defined in (including functions, loops and conditional statements). And since it's in a function here, that first line is equivalent to:
var result = 1;
In the second line:
for (let count = 0; count < exponent; count++) {}
You're looping over exponent - so the code within the {} of the loop will be executed exponent times.
In the third line:
result *= base;
You're multiplying result and base, and assigning the value to result. This line is equivalent to:
result = result * base;
Final line:
return result;
This line stops the function and returns result. The return means that whenever a function is called, it essentially is replaced with the return value (like in this line):
console.log(power(2, 10));
This calls power() with arguments 2 and 10, and logs the returned value to the console.
This example is a simple approach of building and executing an exponential function in JavaScript.
That said, we know that the below will essentially be creating something like the following in pseudocode:
print the result of (number to the power of some other number)
The code walkthrough:
// initialize a constant variable named 'power' as a function declaration with two arguments, 'base' and 'exponent' which will be used inside the function
const power = function(base, exponent) {
// declare and initialize variable called 'result' and set it with value of 1
// why this is 1, is because any number to the power of 1 is itself, so rather than setting this to 0, this must be 1 to ensure that the exponential function works accurately
let result = 1;
// let count = 0; this will initialize a variable named count to be used within the loop
// count < exponent; this is the conditional statement, it means that the loop will continue looping until the condition is met, meaning loop until 'count' is no longer less than 'exponent'
// count++; this increments the value of the initial variable, in this case 'count' for every trip through the loop for the duration that the condition statement remains true
for (let count = 0; count < exponent; count++) {
// multiply the 'result' variable by the 'base' variable and set it as the new value of the 'result' variable
result *= base;
}
// return the 'result' variable so that it is now available outside of the function
return result;
};
// pass in the 'base' and 'exponent' arguments for the function 'power' in order to get the value (effectively, 2^10), and then print this value to the console
console.log(power(2, 10));
// 1024

Difference in count++ and count+1 in higher-order functions

Example 1
function makeCounter() {
let count = 0;
return function() {
return count++;
};
}
let counter = makeCounter();
alert( counter() );
alert( counter() );
Above alerts 0 and 1 respectively.
Example 2
function makeCounter() {
let count = 0;
return function() {
return count+1;
};
}
let counter = makeCounter();
alert( counter() );
alert( counter() );
This alerts 1 and 1 respectively
In programming count++ is equivalent to count+1 , then why is the difference in above two examples. I know its something related to closure property and hoisting. But understand perfectly. Could you guys help.
Note: Please let me know whether I should change the title of the question if it does not make sense.
The expression count++ evaluates count, adds 1, stores the result in count, but the overall result (the net value of count++) is the original value of count.
The expression count + 1 evaluates count, adds 1, and returns the result. The value of count is not changed.
Interestingly, while it's possible to mimic ++count (pre-increment) with an alternative expression
var inc = (count += 1);
there's really no way (I can think of) to mimic count++ cleanly without using a function, because there's no getting around the need for a temporary storage location:
var inc = () => { let tmp = count; count += 1; return tmp }();
The operator semantics of post-increment ++ dates from C in the 1970s and probably earlier, and has been copied by many other languages, including JavaScript. Folklore (as I remember it, being an old person) held that the pre- and post-increment operators were inspired by addressing modes available in the DEC PDP-11 instruction set, but that's always seemed fairly unlikely to me.
In your first example, you are post incrementing, i.e. adding 1 after the declaration and use. If you used ++count (pre incrementing) you would get 1 and 2 in your alerts.
In your second example, you do not store the value of count+1 back into count, so on the second time around, count is still 0 and you get the same result again.

JavaScript: Writing a reduce function, trouble with callback function that subtracts values

I'm working to solve a code challenge in JavaScript where I am tasked with creating a function, called reduce, that will reduce a collection to a value which is the accumulated result of calling a function on each item over which I've iterated. The three parameters to include are array, callback, and start. Start is the index at which to begin, and if not provided as an argument defaults to the index zero.
Below is what I have currently:
function reduce(array, callback, start) {
if(typeof start === 'number'){
var initVal = start;
} else {
var initVal = 0;
}
return array.reduce(callback, initVal);
}
I have some tests against which I can test my solution, and my current work is failing only one test involving a callback function that subtracts the values. Here is the test I'm currently failing:
var difference = function(tally, item) {return tally - item; };
var total = reduce([1, 2, 3], difference);
expect(total).to.equal(-4);
Guidance is greatly appreciated.
Edited to add working solution:
function reduce(array, callback, start) {
if( typeof start === 'undefined' ){
return array.reduce(callback);
} else {
return array.reduce(callback, start);
}
}
Your code does not work since you're misusing the start which is intended to be an element index to start with with the initial value.
So for the [1, 2, 3] array as an input and the subtraction function as a callback what you are getting is:
The reducer accumulator is initialised with 0 (what you are supposed to not do actually)
0 - 1 -> -1
-1 - 2 -> -3
-3 - 3 -> -6
What you should have done instead:
There is no third parameter passed, so you're iterating from the beginning of the array.
Accumulator is not initialised explicitly, so the first element is passed to it, hence acc = 1
1 - 2 -> -1
-1 - 3 -> -4

Where is the variable being stored during a closure?

Ok, I understand that in the code below a closure is created when the parent function counter returns an object with a method called count. But can somebody clarify if I'm understanding the control flow correctly? After the counter function is assigned to variable c the first time the method it is invoked, by c.count(), the output is 1. And each additional time it is called the stored n is incremented and the new value is returned. I understand this is possible through the magic of closure so that by calling this four times I get a new value each time ending with 4 instead of simply getting 1 four times over. But where is the value that n holds each time "hanging out" while it waits for me to call the count method again to increment the most recently created value? What will it take for n to have a clean slate again as 0? If I declare a new variable and assign the function counter to it? Trying to wrap my head around all this and these questions occurred to me. I'm not sure if what I'm asking is obnoxious or painfully obvious-- thank you in advance.
function counter() {
var n = 0;
return {
count: function() { return ++n; },
};
}
var c = counter();
console.log(c.count()); // 1
console.log(c.count()); // 2
console.log(c.count()); // 3
console.log(c.count()); // 4
where is the value that n holds each time "hanging out" while it waits for me to call the count method again to increment the most recently created value?
Variable n, of course, is hold in memory. Its behavior is just like on global scope, but within the counter scope.
What will it take for n to have a clean slate again as 0?
Reset it.
I've rewritten your example in self-executing function style to make it clearer. Hope it helps.
var c = (function counter(){
var n = 0;
return {
count: function() { return ++n; },
//don't use keyword 'var', it will create a new variable instead of reseting n
reset: function() { n = 0},
};
})();
console.log(c.count()); // 1
console.log(c.count()); // 2
console.log(c.count()); // 3
console.log(c.count()); // 4
console.log(c.reset());
console.log(c.count()); // 1
console.log(c.count()); // 2
console.log(c.count()); // 3
console.log(c.count()); // 4
Variables in a closure are not stored on any object available from within JavaScript itself, so it is impossible to reset it unless you add another function for it in the object you return:
function counter() {
var n = 0;
return {
count: function() { return ++n; },
reset: function() { n = 0; }
};
}

Categories