How to change a global variable with an if/else statement - javascript

I have this code where i want to change var n if the var thisRoll is not 'green', but i only get undefined in the output from console.log(n)
var thisRoll = 'red'
var n;
var base_bet = 1;
function betInput(thisRoll, n) {
var x;
if (thisRoll === 'green') {
x = base_bet;
n = 0;
} else {
n = n + 1;
}
return x;
}
var X = betInput(thisRoll);
console.log(X);
console.log(n);
Shouldn't it add 1 when the thisRoll aren't 'green'?

Because your n is also a parameter in the function. So it hides the outer variable n in the function and when you access the n, it refers to the parameter variable. To work with the global n, you need to remove the parameter, or change it's name.
function betInput(thisRoll) {
var x;
if (thisRoll === 'green') {
x = base_bet;
n = 0;
} else {
n = n + 1;
}
return x;
}

The function betInput(thisRoll, n) contains a parameter n which shadows the global variable n. Calling that function using betInput(thisRoll) merely sets the local n to a default value.
(The fact that Javascript is lax on this - and many other things - does make it difficult to write stable code in the language).
Simply remove n from the function parameter list and all will be well.

Remove the parameter in your function. There's n there, which makes it scoped to the function.
function betInput(thisRoll, n) {
//------------------------^^^
Change your function to:
function betInput(thisRoll) {
So that, n will reference your global variable, otherwise n is undefined in your function scope

Related

Can a function read the binding of another function?

I'm currently learning javascript and I would appreciate some help.
I've been playing around trying to create a program that would multiply two numbers without using the * operator. I already found an easier way to do it than my approach but I'd like to know why the code I wrote doesn't work:
function addToItself(a) {
a = a + a;
return a;
}
function times(b) {
for (count = 0; count < b; count++) {
addToItself(a)
}
return a;
}
function multiply (x, y) {
a = x;
times(y);
}
let output = multiply(5, 2);
alert(output);
Is it not working because the binding "a" in the addToItself function has a local scope and the multiply function can't read it or is it something else?
Thanks a lot in advance!
The issue is with the scope of each variable. In JavaScript, a variable declated within a function is scoped to that function. This means that a variable declared within a function can only be accessed within the function. Scopes are nested, so a variable declared globally is accessible inside a function too, though that's often discouraged.
Additionally, function arguments (such as a in addToItself and b in times) are treated like variables scoped to the function.
I would advise looking at the MDN docs for "scope" and familiarizing yourself with how variables are scoped in JavaScript.
I have included a fixed version of your code is below, for reference:
function addToItself(a) {
// I used a new variable here since reassigning to an argument is discouraged
const twoA = a + a;
return twoA;
}
console.log('5 + 5 = ' + addToItself(5));
function times(value, times) {
let temp = 0;
for (let count = 0; count < times; count++) {
temp += value;
}
return temp;
};
console.log('5 * 5 = ' + times(5, 5));
No you can't read variable inside another function, there are easier way, like
function multiply(x, y) {
var result = 0;
for (var count = 0; count < y; count++) {
result += x
}
return result;
}
console.log("5 * 2 = " + multiply(5, 2));

How to make the return variable hold a new value after Increment/Decrementing it in a function?

Everytime I run this function, the p1_Balance will always reset back to 10 and will not hold the new value of an increment or decrement.
function Balance() {
var p1_Balance=10;
var x= Math.floor(10*Math.random());
if (x<5) {
p1_Balance=p1_Balance-1;
} else {
p1_Balance=p1_Balance+1;
}
return p1_Balance;
}
Pass p1_Balance into the function instead of initializing it each time the function is called with: var p1_Balance = 10;
p1_Balance should be declared outside the scope of the function (meaning not within the function itself). Otherwise, each time the function is called, the initializer that sets the value to 10 runs as well.
var p1_Balance=10;
function Balance(){ ...
You can use Javascript closures to create a function that does what you want, as you can see below:
var Balance = (function() {
var p1_Balance = 10;
return function() {
var x = Math.floor(10 * Math.random());
if (x < 5)
return p1_Balance += 1;
else
return p1_Balance -= 1;
};
})();
for (var i = 0; i < 10; i++)
console.log(Balance());
Alternatively, you will need to define the p1_Balance variable outside the function or pass it as an argument.
There could be several solutions:
one is declaring p1_Balance as a global variable.
var p1_Balance=10;
function Balance(){
var x= Math.floor(10*Math.random());
if (x<5) {
p1_Balance=p1_Balance-1;
}
else {
p1_Balance=p1_Balance+1;
}
return p1_Balance;
}
another is you could pass balance as a function parameter:
function Balance(p1_Balance){
var x= Math.floor(10*Math.random());
if (x<5) {
p1_Balance=p1_Balance-1;
}
else {
p1_Balance=p1_Balance+1;
}
return p1_Balance;
}
.....
value = Balance(10);// value=something that you want to change by that function.

add a memoization to recursive algorithm

I have written a function for partitioning a number:
var combinations = function (i) {
var mem = [];
function inner(n, r, m) {
for (var k = m; k <= n; k++) {
if (k == n) {
r.push(k);
mem[r] = 1;
return mem;
}
else {
var copy = r.slice(0);
copy.push(k);
inner(n - k, copy, k);
}
}
}
return inner(i, [], 1);
}
In second step I would like to add a memoization to this algorithm, but can't think of implementing it the right way, beause there is no return statement until the very end (when return is specified e.g. in faactorial or fibbinacci I can add the memoization).
Can anybody drive me to the right direction?
[edit]
I need this algorithm to be as fast as possible. This is a competition for a kata at codewars: link
There is a requirement it must be executed under 6000ms for input up to 330.
That's the best algorithm I can think of, except how to store the partial results.
Here's a much simpler code that works:
function nr_partitions(n) { return p(n, n); }
function p(sum,largest) {
if (largest == 0) { return 0; }
if (sum == 0) { return 1; }
if (sum < 0) { return 0; }
return p(sum, largest-1) + p(sum-largest, largest);
}
It uses a well-known recurrence, p(n,k) = p(n,k-1) + p(n-k, k), where p(n.k) denotes the number of partitions of n where the largest part is at most k (e.g. p(3, 2)=2 because we only count 1+1+1,1+2, but not 3). For k=n we get the number of all partitions of n.
Adding memozation involves storing dictionary mapping pairs (sum, largest) to p(sum, largest).
I would go along the lines of:
var cache = {};
var combinations = function (i) {
if ( cache[i] ){
return cache[i];
};
var mem = [];
function inner(n, r, m) {
for (var k = m; k <= n; k++) {
if (k == n) {
r.push(k);
mem[r] = 1;
return mem;
}
else {
var copy = r.slice(0);
copy.push(k);
inner(n - k, copy, k);
}
}
}
cache[i] = inner(i, [], 1);
return cache[i];
}
But you'll have to modify your algorithm to make use of that cache (compute the biggest terms first ?)
Depending on your other requirements, you might want to consider using underscore.js which has its own _.memoize function.
The secret of memoization is that it exploits how closures work. When you define a function inside another scope, it has access to everything in that scope. When you return that function to somewhere outside the scope, it carries references to everything it can see inside the scope.
So to implement memorization, you need to make a function that returns another function, one that does the memorization check before calling the inner one.
Your code will look something like this:
/**
* Because we'll be returning "a function that returns a function" below,
* this needs to be executed immediately so combinations() is just
* a standalone function.
*/
var combinations = (function(i) {
/**
* mem needs to stay outside the scope of your inner function.
* If it's in a closure like this, JavaScript will keep its value
* around as long as combinations still exists.
*/
var mem = [];
/**
* A memoization wrapper should return a memoized function
*/
return function(i) {
/**
* Check if mem[i] is set and return it if it has been
*/
if(mem[i] !== undefined) {
console.log('returning memoized value');
return mem[i];
}
function inner(n, r, m) {
for (var k = m; k <= n; k++) {
if (k == n) {
r.push(k);
mem[r] = 1;
return mem;
}
else {
var copy = r.slice(0);
copy.push(k);
inner(n - k, copy, k);
}
}
}
/**
* If the value needs to be computed, we can set it at the same time
* as we return it instead of putting it in a temporary variable.
*/
console.log('computed');
return mem[i] = inner(i, [], 1);
}
}()); /** <--- That's the rest of the automatic execution */
console.log(combinations(5));
console.log(combinations(5));

Javascript - how to detect how many functions are being called? (multiple parentheses)

Let me propose an example that works, then follow up with what fails, highlighting the point to my question.
Here, we have 3 functions being called (1 named, 2 anonymous):
var add = function(a, b) {return a+b};
var multiply = function(a, b) {return a*b};
function myFunction(fxn) {
return function(x) {
return function(y) {
return fxn(x,y);
}
}
}
myFunction(add)(2)(3)
Understandably, this call fails:
myFunction(add)(2)(3)(4)
How would I detect how many functions are being called? In the 2nd call, I'm calling 4 functions (1 named, 3 anonymous).
How would I rewrite the myFunction function in a way that compensated for any given amount of calls? I know we can detect how many arguments a function was given, but is there a way to detect how many functions are being called? I hope I worded this correctly. Thanks.
To find out if a variable contains a reference to a function you can use below code:
if (typeof(v) === "function") alert("This is a function")
Based on above you can find out on how many nested functions there are
function myFunction() {
return function() {
return function() {
return 1 + 2;
}
}
}
var count = 0;
var v = myFunction();
while (typeof(v) === "function") {
count++;
v = v();
}
alert("Nr of nested functions: " + count)
Even if this has no practical use case I can think of, this is a possible solution:
var add = function(a, b) {
return a + b
};
var multiply = function(a, b) {
return a * b
};
var counter = 0;
var result = 0;
function myFunction(fxn) {
counter = 1;
result = 0;
return function first(x) {
++counter;
return function second(y) {
++counter;
x = result ? result : x;
result = fxn(x, y);
return second;
}
}
}
myFunction(add)(1)(2)(3)(4);
alert('Result is: ' + result + '; Parentheses count: ' + counter);

What is the difference between naming functions or not in javascript?

What is the difference between
settings = {
edit: function (key, value) {
return anotherFunction(key, value) {
return value * 2;
};
}
};
and
settings = {
edit: function edit(key, value) {
return anotherFunction(key, value) {
return value * 2;
};
}
};
?
There's no difference when executing.
However, in the second case (named function), you can call the function recursively easier because it has a name.
For example, with a named function you can do:
fact: function factorial(n) {
if(n == 0) return 1;
return n * factorial(n-1); //You can do this with a named function easily
}
Without a name, this would be tricky.
Cheers
The essential difference is better debugging. In your developer tools, the named function in your second example will appear as edit in a backtrace; your first example will appear as anonymous. This can be extremely confusing when you're 10 function deep, and they are all called anonymous.
There are three reasons to give a function an inherent name. The first is that everyone does it. It's what everyone is used to.
function factorial(n) {
var accum = 1, i;
for (i = 1; i <= n; i++) {
accum *= i;
}
return accum;
}
The second is to understand stack traces better, as #meagar wrote.
The third is to let you write call functions recursively.
var factorial = function(n) {
var a = 1;
return (function factRecursive(k, a) {
if (k >= 2) {return factRecursive(k - 1, k * a)}
else {return a;}
})(n, a);
}

Categories