I have a 'twice' function that return 2 of the argument passed into it. I also have another function 'runTwice' that counts the number of times it called the 'twice' function (the idea being that I want the 'twice' function to only run 'twice' no matter how often it is called via the 'runTwice' function). Can you please help?
Functions are given below:
var count = 1;
function twice(num){
return num*2;
}
function runTwice(func){
if (count<3){
count++;
return func;
} else {
return 'Function cannot run!';
}
}
var myFunc = runTwice(twice)
var output = [];
for (var i = 0; i < 3; i++){
output.push(myFunc(i));
}
console.log(output);
I would like the output to be [0, 2, 'Function cannot run!'].
I can make this work if I count the 'twice' function directly but I am looking to understand why this doesn't work as presented above.
Just for fun I'll make a generic expireAfter(invocable[, times[, message]]) function:
function expireAfter(invocable, times = 2, message = 'Function cannot run!') {
return function expires() {
if (times > 0) {
times--;
return invocable.apply(this, arguments);
}
return message;
}
}
function twice(n) {
return n * 2;
}
var myFunc = expireAfter(twice);
console.log(Array(3)
.fill()
.map((_, index) => myFunc(index))
);
The function runTwice should return another function that will decide whether to call the function func (using Function.prototype.apply) or to return a string message instead:
function twice(num){
return num * 2;
}
function runTwice(func){
var count = 0; // this will be trapped in a closure along with func
return function() { // this is the function that gets called
count++; // it increments its version of the count variable
if(count <= 2) // if count is less than 2
return func.apply(this, arguments); // then it calls the function func with whatever arguments passed into it and return the returned value of that call
return "Not available anymore!"; // otherwise (count > 2), then it returns a string
}
}
var myFunc = runTwice(twice);
for (var i = 0; i < 3; i++){
console.log(myFunc(i));
}
Even better:
You can pass in the number of times allowed as well:
function double(num) {
return num * 2;
}
function triple(num) {
return num * 3;
}
function run(func, times){
var count = 0; // this will be trapped in a closure along with func and times
return function() { // this is the function that gets called
count++; // it increments its version of the count variable
if(count <= times) // if count is less than times
return func.apply(this, arguments); // then it calls the function func with whatever arguments passed into it and return the returned value of that call
return "Not available anymore!"; // otherwise (count > times), then it returns a string
}
}
var double2times = run(double, 2); // double2times can only be called 2 times
var triple5times = run(triple, 5); // triple5times can only be called 5 times
for (var i = 0; i < 10; i++){
console.log("Double:", double2times(i));
console.log("Triple:", triple5times(i));
}
Related
Let's consider I have the following function call,
function add(){
x = 0 ;
for(i = 0 i < ##; i++){ // need to run a loop four times
x+=1
}
}
Let's consider I am trying to Implement the function that will add one on each subsequent call, like below
console.log(add()()().getValue()); // 3
console.log(add().getValue()); // 1
console.log(add()().getValue()); // 2
A call to add must return a function which also has a getValue method, and each call to that function must return the same thing. So:
function add() {
var x = 1;
function inner() {
x += 1;
return inner;
}
inner.getValue = function () {
return x;
}
return inner;
}
console.log(add()()().getValue()); // 3
console.log(add().getValue()); // 1
console.log(add()().getValue()); // 2
My guess is they were expecting you to use toString() which is not the greatest way of doing this.
function add(x = 0) {
function next() {
return add(x+1);
}
next.toString = function () {
return x;
};
return next;
}
console.log("example 1", add()()()());
console.log("example 2", add()()()()()()()()());
I think you are trying to emulate the behavior of generator functions. Here is a snippet that illustrates one way you could do it with a generator.
function* adder() {
let x = 0;
while (true) {
yield x + 1;
x++;
}
}
const add = adder();
const firstValue = add.next();
const secondValue = add.next();
const thirdValue = add.next().value;
I have an exercise about JavaScript. This exercise requires me to use higher-order functions. I have managed to specify some of the functions so far, but when I try to execute the code, the result does not seem to work properly. I have some images to give you an idea, hopefully, you can help me correct this.
The thread is: Write the function loop(loops, number, func), which runs the given function the given number of times. Also write the simple functions halve() and square().
This is my code:
function loop(loops, number, func) {
var loops = function(n) {
for (var i = 0; i < n; i++) {
if (i < 0) {
console.log('Programme ended')
}
if (i > 0) {
return n;
}
}
}
}
var halve = function(n) {
return n / 2
}
var square = function(n) {
return n ** 2;
}
console.log(halve(50));
console.log(loop(5, 200, halve));
console.log(loop(3, 5, square));
console.log(loop(-1, 99, halve));
Your current loop function declares an inner function and then exits. Ie, nothing actually happens -
function loop(loops,number,func){
// declare loops function
var loops= function(n){
// ...
}
// exit `loop` function
}
One such fix might be to run the supplied func a number of times in a for loop, like #code_monk suggest. Another option would be to use recursion -
function loop (count, input, func) {
if (count <= 0)
return input
else
return loop(count - 1, func(input), func)
}
function times10 (num) {
return num * 10
}
console.log(loop(3, 5, times10))
// 5000
so first things first: Higher-Order functions are functions that work on other functions.
The reason why you get undefined is because you are calling a function which doesn't return anything.
function x(parameter){
result = parameter + 1;
}
// -> returns undefined every time
console.log(x(5));
// -> undefined
function y(parameter){
return parameter+1;
}
// -> returns a value that can be used later, for example in console.log
console.log(y(5));
// -> 6
Second, you are using n for your for loop when you should probably use loops so it does the intended code as many times as "loops" indicates instead of the number you insert (i.e. 200, 5, 99).
By having the "console.log" inside a loop you may get a lot of undesired "programme ended" in your output so in my version I kept it out of the loop.
The other two answers given are pretty complete I believe but if you want to keep the for loop here goes:
function loop(loops, number, func){
if(loops>0){
for(let i = 0; i< loops; i++){ // let and const are the new ES6 bindings (instead of var)
number = func(number)
}
return number
}
else{
return "Programme ended"
}
}
function halve(n) { // maybe it's just me but using function declarations feels cleaner
return n / 2;
}
function square(n) {
return n ** 2;
}
console.log(halve(50));
console.log(loop(5, 200, halve));
console.log(loop(3, 5, square));
console.log(loop(-1, 99, halve));
Here's one way
const loop = (loops, n, fn) => {
for (let i=0; i<loops; i++) {
console.log( fn(n) );
}
};
const halve = (n) => {
return n / 2;
};
const square = (n) => {
return n ** 2;
};
loop(2,3,halve);
loop(4,5,square);
I tested performance with a script from "Secrets of Javascript Ninja":
function isPrime(number) {
if (number < 2) {
return false;
}
for (let i = 2; i < number; i++) {
if (number % i === 0) {
return false;
}
}
return true;
}
console.time("isPrime");
isPrime(1299827);
console.timeEnd("isPrime");
console.time("isPrime");
isPrime.apply(1299827);
console.timeEnd("isPrime");
And the result is:
isPrime: 8.276ms
isPrime: 0.779ms
Seems that "apply" is faster?
Your comparison is not accurate, because the first parameter passed to apply is the this value of the called function, and the second parameter passed to apply is an array of parameters that function is to be called with. So, your apply is not calling isPrime with any parameters, so no iterations run, because the condition i < number is not fulfilled when i is 2 and number is undefined:
function isPrime(number) {
console.log('calling with ' + number);
if (number < 2) {
return false;
}
for (let i = 2; i < number; i++) {
if (number % i === 0) {
return false;
}
}
return true;
}
console.time("isPrime");
isPrime(1299827);
console.timeEnd("isPrime");
console.time("isPrime");
isPrime.apply(1299827);
console.timeEnd("isPrime");
If you use apply properly and pass in undefined, [1299827], the result is as expected, very similar. You should also use performance.now() for better precision than console at the millisecond level, though for such a quick operation you might not see that might difference anyway:
function isPrime(number){
console.log('calling with ' + number);
if(number < 2) { return false; }
for(let i = 2; i < number; i++) {
if(number % i === 0) { return false; }
}
return true;
}
const t1 = performance.now();
isPrime(1299827);
const t2 = performance.now();
isPrime.apply(undefined, [1299827]);
console.timeEnd("isPrime");
const t3 = performance.now();
console.log(t2 - t1);
console.log(t3 - t2);
The syntax for .apply is
function.apply(thisArg, [argsArray])
the first parameter thisArg refers to the value of 'this' when calling the function, in your case isPrime.apply(1299827) you passed in 1299827 as 'this' but no parameter, so it's really isPrime(), the for loop is not excuted so it's faster
more on .apply here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
You have to read this.
reference: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
This point is Array.prototype.apply(context = this, args = []), so your code is wrong.
Change your code to this.
// incorrect.
isPrime.apply(1299827);
// correct.
isPrime.apply(this, 1299827);
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.
I'm not sure if what I am trying to do is impossible or not.
Consider this function:
function p(num) {
if (!num) num = 1;
return p.bind(null, num + 1);
}
if you call p(), inside the function num = 1, if you call p()(), num = 2 and so on. But, there is no way to actually return or obtain num from p because it always returns a bound copy of itself with the number trapped in its unexecutable closure.
Anyway, I'm curious (a) if there is a way to pull the argument out of the bound function, or (b) there is another way to count in this fashion.
I have two answers depending on what you want. If you simply want something "imperative" and "stateful":
function p() {
if (!p.num) p.num = 0;
p.num = 1 + p.num;
return p;
}
p();
p.num; // 1
p();
p.num; // 2
p()();
p.num; // 4
p()()();
p.num; // 7
Or if you want it to be "stateless":
function p() {
p.num = 0;
function gen_next(prev) {
function next() {
return gen_next(next);
}
next.num = prev.num + 1;
return next;
}
return gen_next(p);
}
p().num; // 1
p()().num; // 2
p()()().num; // 3
p()().num; // still 2
p().num; // still 1