I am having trouble understanding how to return information to the first function from the second when there are multiple arguments. Now I know the following code works.
function One() {
var newVal = 0;
newVal = Too(newVal);
console.log(newVal);
}
function Too(arg) {
++arg;
return arg;
}
But what if I try to complicate things by adding arguments and a setinterval.
function One() {
var newVal = 0;
var z = 3;
var y = 3;
var x = 1;
newVal = Too(newVal);
var StopAI2 = setInterval(function () {
Too(x, y, z, newVal)
}, 100);
}
function Too(Xarg, Yarg, Zarg, newValarg) {
Xarg*Xarg;
Yarg*Yarg;
Zarg*Zarg;
++newValarg;
return newValarg;
}
I'm not sure what to do with the newVal = line of code. I only want to return the newVal not x,y,z.
This is what I think you're trying to ask:
How can I operate on the 4th argument to a function when only one argument is passed?
The answer to that question is this:
If you want to operate on the 4th argument of a function, at least 4 arguments must be passed to the function.
There are a few ways you can approach your problem differently.
#1
If there's one argument that is always necessary, make sure it's the first argument:
function Too(mandatoryArg, optionalArg1, optionalArg2) {
alert(++mandatoryArg);
if (optionalArg1) {
alert(++optionalArg1);
}
}
#2
Pass placeholder values for all the undefined or unknown arguments.
You might use null, undefined, or ''.
alert(Too(null, null, 4));
function Too(optArg1, optArg2, mandatoryArg) {
alert(++mandatoryArg);
}
#3
Make a decision based on the number of arguments:
function Too(optArg1, optArg2, optArg3) {
var numArgs = arguments.length;
if (numArgs === 1) {
alert(++optArg1);
}
if (numArgs === 3) {
alert(++optArg3);
}
}
EDIT
"Will this update a variable in the first function?"
Let's use an actual example that demonstrates something:
function one() {
var a = 0;
var b = 25;
var c = 50;
var d = -1;
d = two(a, b, c);
alert("a: " + a);
alert("b: " + b);
alert("c: " + c);
alert("d: " + d);
}
function two(a, b, c) {
++a;
++b;
++c;
if (arguments.length === 1) {
return a;
}
if (arguments.length === 3) {
return c;
}
}
Invoking one() will cause the following alerts:
a: 0
b: 25
c: 50
d: 51
Only the value of d is modified in function one().
That's because d is assigned the return value of two().
The changes to a, b, and c, inside two() have no effect on the values of a, b, and c inside one().
This would be the case even if the arguments for two() were named a, b, and c.
Here's a fiddle with the code above.
EDIT #2
Here is one way you could create functions that move a game object:
var FORWARD = 0;
var BACK = 1;
var LEFT = 2;
var RIGHT = 3;
// use an object with three values to represent a position
var pos = {
x: 0,
y: 0,
z: 0
};
pos = moveObject(pos, FORWARD);
printPosition(pos);
pos = moveObject(pos, LEFT);
printPosition(pos);
pos = moveObject(pos, FORWARD);
printPosition(pos);
pos = moveObject(pos, LEFT);
printPosition(pos);
// invoking moveObject() with one argument
// will move the object forward
pos = moveObject(pos);
printPosition(pos);
function moveObject(position, direction) {
// assume FORWARD if no direction is specified
if (typeof direction === 'undefined') {
direction = FORWARD;
}
if (direction === FORWARD) {
++position.z;
}
if (direction === BACK) {
--position.z;
}
if (direction === LEFT) {
--position.x;
}
if (direction === RIGHT) {
++position.x;
}
return position;
}
function printPosition(pos) {
alert(pos.x + ", " + pos.y + ", " + pos.z);
}
Here's a fiddle that shows a working demo of another approach.
There are two concepts that are at play here.
1 . Variable number of function parameters (or optional parameters).
If you are going to call the same function with different number of parameters (this will eventually lead to a world of headache), you need to determine (inside the function) how this function was called. You can use arguments object available inside each function:
function Too() {
if (arguments.length == 4) {
arguments[0]*arguments[0];
arguments[1]*arguments[1];
arguments[2]*arguments[2];
return ++arguments[3];
} else if (arguments.length == 1) {
return ++arguments[0];
} else {
// you decide what to do here
}
}
2 . Asynchronous code execution.
Realize that Too which is called when interval expires, executes well after One completes and returns. If you want Too to affect newVal variable, and somehow get at this new value afterwards, - make newVal variable global.
Related
A friend of mine challenged me to write a function that works with both of these scenarios
add(2,4) // 6
add(2)(4) // 6
My instinct was the write an add() function that returns itself but I'm not sure I'm heading in the right direction. This failed.
function add(num1, num2){
if (num1 && num2){
return num1 + num2;
} else {
return this;
}
}
alert(add(1)(2));
So I started reading up on functions that return other functions or return themselves.
http://davidwalsh.name/javascript-functions
JavaScript: self-calling function returns a closure. What is it for?
JavaScript: self-calling function returns a closure. What is it for?
I am going to keep trying, but if someone out there has a slick solution, I'd love to see it!
I wrote a curried function whose valueOf() method and function context (this) are bound with the sum no matter how many arguments are passed each time.
/* add function */
let add = function add(...args) {
const sum = args.reduce((acc, val) => acc + val, this);
const chain = add.bind(sum);
chain.valueOf = () => sum;
return chain;
}.bind(0);
/* tests */
console.log('add(1, 2) = ' + add(1, 2));
console.log('add(1)(2) = ' + add(1)(2));
/* even cooler stuff */
console.log('add(1, 2)(3) = ' + add(1, 2)(3));
console.log('add(1, 2, 3)(4, 5)(6) = ' + add(1, 2, 3)(4, 5)(6));
/* retains expected state */
let add7 = add(7);
console.log('let add7 = add(7)');
console.log('add7(3) = ' + add7(3));
console.log('add7(8) = ' + add7(8));
The reason why both mechanisms are required is because the body of add() must use the called function's bound context in order to access the sum of the intermediate partial application, and the call site must use the valueOf() member (either implicitly or explicitly) in order to access the final sum.
There is an article on Dr.Dobs Journal about "Currying and Partial Functions in JavaScript" which describes exactly this problem.
One solution found in this article is:
// a curried add
// accepts partial list of arguments
function add(x, y) {
if (typeof y === "undefined") { // partial
return function (y) {
return x + y;
};
}
// full application
return x + y;
}
function add(num1, num2){
if (num1 && num2) {
return num1 + num2;
} else if (num1) {
return function(num2){return num1 + num2;};
}
return 0;
}
The concept that you're looking for is called currying and it has to do with function transformation and partial function application. This is useful for when you find yourself calling the same function over and over with mostly the same arguments.
An example of implementing add(2)(6) via currying would look something like this...
function add(x,y) {
if (typeof y === 'undefined') {
return function(y) {
return x + y;
}
}
}
add(2)(4); // => 6
Additionally, you could do something like this...
var add6 = add(6);
typeof add6; // => 'function'
add6(4); // => 10
var add = function(){
// the function was called with 2 arguments
if(arguments.length > 1)
arguments.callee.first_argument = arguments[0];
// if the first argument was initialized
if(arguments.callee.first_argument){
var result = arguments.callee.first_argument + arguments[arguments.length - 1];
arguments.callee.first_argument = 0;
return result;
}else{// if the function was called with one argument only then we need to memorize it and return the same function handler
arguments.callee.first_argument = arguments.callee.first_argument || arguments[0];
return arguments.callee;
}
}
console.log(add(2)(4));
console.log(add(2, 4));
An extended solution which depends on the environment:
function add(){
add.toString = function(){
var answer = 0;
for(i = 0; i < add.params.length; i++)
answer += add.params[i];
return answer;
};
add.params = add.params || [];
for(var i = 0; i < arguments.length; i++)
add.params.push(arguments[i])
return add;
}
console.log(add(2)(4)(6)(8))
console.log(add(2, 4, 6, 8));
We can use the concept of closures which is provided by Javascript.
Code snippet:
function add(a,b){
if(b !== undefined){
console.log(a + b);
return;
}
return function(b){
console.log(a + b);
}
}
add(2,3);
add(2)(3);
In general you need to have an agreement whether the function should return a function (for calling with more arguments) or the end result. Imagine the add function would have to work like this as well:
add(1, 2, 3)(4, 5) // -> 15
...then it becomes ambiguous, because you might want to call again:
add(1, 2, 3)(4, 5)(6) // -> 21
...and so add(1, 2, 3)(4, 5) should have returned a function, and not 15.
You could for instance agree that you have to call the function again, but without arguments, in order to get the numeric result:
function add(...args) {
if (args.length === 0) return 0;
let sum = args.reduce((a, b) => a+b, 0);
return (...args) => args.length ? add(sum, ...args) : sum;
}
console.log(add()); // 0
console.log(add(1,2,3)()); // 6
console.log(add(1,2,3)(4,5)()); // 15
console.log(add(1,2,3)(4,5)(6)()); // 21
One may think that he/she has to invoke the same function two times, but if you think deeply you will realize that the problem is pretty straight forward, you have to invoke the add function one time then you need to invoke what ever the add function returns.
function add(a){
return function(b){
return a+b;
}
}
console.log(add(20)(20));
//output: 40
you can return function as many as time you want. suppose for y = mx+c
const y= function (m){
return function(x){
return function (c){
return m*x+c
}
}
}
console.log(y(10)(5)(10));
//out put: 60
Function addOne returns undefined result...
const t = 5;
const b = 8;
function addOne () {
add (t + b);
return addOne;}
Pls help to get a sum of 5 + 8 with this function.
const t = 5;
const b = 8;
function addOne () {
return t+b;
}
console.log(addOne()); //13
I am not sure what you are asking, since your method's name is not matching with your implementation. But here are some code that might help you:
const t = 5;
const s = 8; // Note that I have renamed the parameter's name
function addOne () {
return s + 1;
}
function addOneToParameter(x) {
return x + 1;
}
function addTwoConstants () {
return t + s;
}
function addTwoParameters (a, b) {
return a + b;
}
console.log(addOne()); // 9 (The constant 's' + 1)
console.log(addTwoConstants()); // 13 (The constant 's' + constant 't')
console.log(addTwoParameters(1,2)); // 3 (The first parameter + the second parameter)
console.log(addOneToParameter(4)); // 5 (The parameter + 1)
In your original question, you don't need to use a function to perform an addition of two integers. In other words, simply use '+' as operand. Furthermore, pay attention how to return a value from your function.
I'm trying to create a simple program in javascript where the Fibonacci square can be created by a random number sequence but I can't seem to connect both parts of my code. The first side being: the call for a random number and the second part: calculating the Fibonacci square.
var n = function getRandomNum() {
return Math.floor(Math.random()*100) +1;
}
function fib(x) {
if (x < 2) {
return x;
} else {
return fib(x - 1) + fib(x - 2);
}
}
console.log(fib(n));
Tell me where I'm going wrong. These are the errors I get when I run it.
RangeError: Maximum call stack size exceeded
at fib:7:13
at fib:11:12
at fib:11:12
at fib:11:12
at fib:11:12
at fib:11:12
Aside from not invoking the random number generator, you're using a very poorly optimized algorithm. If you think through all the redundant calls that need to take place, you'll see why the stack limit is reached.
var n = function getRandomNum() {
return Math.floor(Math.random() * 100) + 1;
}(); // <-- quick inline invocation... not normally how you'd use this.
console.log(n);
function fib(x) {
function _fib(x, a, b) {
if (x < 2) {
return a;
}
return _fib(x - 1, b, a + b);
}
return _fib(x, 0, 1);
}
console.log(fib(n));
Since you don't call n function, you should call it like the following.
var n = function getRandomNum() {
return Math.floor(Math.random()*100) +1;
}
function fib(x) {
if (x < 2) {
return x;
} else {
return fib(x - 1) + fib(x - 2);
}
}
console.log(fib(n));
But, there's a huge problem in your code, as #rock star mentioned, there's no any optimizing process in your code. That is why your code has caused the problem on memory leak
To avoid this, you can simply use memoization, click this link you don't have any clue on it.
Javascript Memoization Explanation?
So, your code can be improved like the folloiwng, by adapting memoization algorithm.
var n = function getRandomNum() {
return Math.floor(Math.random()*100) +1;
}
var result = [];
result[0] = 1;
result[1] = 1;
function fib(x) {
var ix, ixLen;
for(ix = 0, ixLen = x; ix < ixLen; ix++){
if(!result[ix]){
result[ix] = result[ix-2] + result[ix-1];
}
}
console.log('n:', x, ' result: ', result[ix-1]);
return result[ix-1];
}
console.log(fib(n()));
Compare the result with this site.
http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibtable.html
I have range function and output functions they works correct,now I want create sum function for using as callbac function in range function,but when some function executed local variable let us say total or sum initialize 0(zero),how can solve this problem?
function range(start,end,callback,step) {
// body...
step=step || 1;
for(i=start;i<=end;i=i+step){
callback(i);
}
}
function output(a) {
// body...
console.log(a);
}
function sum(m){
var total=0;
// some code
}
range(1,5,output);
range(1,5,sum);
function range(start,end,callback,step) {
// body...
var aggregate;
step=step || 1;
for(i=start;i<=end;i=i+step){
aggregate = callback(i, aggregate);
}
}
function output(a) {
// body...
console.log(a);
}
function sum(m, aggregate){
return m + aggregate;
}
range(1,5,output);
range(1,5,sum);
This way you could even do cool stuff like
function conc(m, aggregate) {
return aggregate + m.toString();
}
range(1,5,conc,2); //prints 135
Continuition style code, like you've started it with range(), can get really weird and cumbersome.
And please, please, mind defining your local variables. like i
function range(start,end,callback,step) {
step=step || 1;
for(var i=start; i<=end; i=i+step)
callback(i);
}
function output(...label) {
return function(...args){
console.log(...label, ...args);
}
}
function sum(callback){
var total = 0;
return function(value){
//will log ever intermediate total, because sum() has no way to tell when the sequence is over.
callback(total += +value || 0);
}
}
range(1,5,output('range:'));
range(1,5,sum(output('sum:')));
In this case, I'd prefer using a generator instead, although the higher order functions get obsolete.
function *range(start,end,step) {
step = +step || (end < start? -1: 1);
for(var value = start, count = (end - start) / step; count-- >= 0; value += step)
yield value
}
function sum(iterator){
var total = 0, v;
for(v of iterator) total += +v || 0;
return total;
}
console.log("range:", ...range(1,5))
console.log("sum of range:", sum(range(1,5)))
//just to show that this works with your regular array as well
console.log("sum of array:", sum([1,2,3,4,5]));
//and some candy, as requested by Bergi ;)
//I like to stay with the interfaces as close as possible to the native ones
//in this case Array#reduce
var fold = (iterator, callback, start = undefined) => {
var initialized = start !== undefined,
acc = start,
index = 0,
value;
for(value of iterator){
acc = initialized?
callback(acc, value, index):
(initialized=true, value);
++index;
}
if(!initialized){
throw new TypeError("fold of empty sequence with no initial value");
}
return acc;
}
//and the ability to compose utility-functions
fold.map = (callback, start = undefined) => iterator => fold(iterator, callback, start);
console.log(" ");
var add = (a,b) => a + b; //a little helper
console.log('using fold:', fold(range(1,5), add, 0));
//a composed utility-function
var sum2 = fold.map(add, 0);
console.log('sum2:', sum2( range(1,5) ));
Clearly a range function should not take a callback but be a generator function in modern JavaScript, however you were asking how to write such a callback.
You've already tagged your questions with closures, and they are indeed the way to go here. By initialising a new total within each call of the outer function, you don't need to worry about how to reset a global counter.
function makeSum() {
var total=0;
return function(m) {
total += m;
return total; // so that we can access the result
}
}
var sum = makeSum();
range(1, 5, sum);
output(sum(0));
Won't simply calling the callback on the range array suffice if the callback is not undefined? Like this:
> function range(n, callback) {
const r = [...Array(n).keys()]
if (callback) {
return callback(r)
}
return r
}
> function sum(arr) {
return arr.reduce((a, b) => a + b, 0)
}
> range(10)
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
> range(10, sum)
> 45
I attempted to create a recursive function to iterate through a data set, but it does not properly break out and is infinite
jsfiddle of code shown
var data = [{a: 1,b: 1}, {a: 2,b: 2}],z = 0;
function some(a, b, cbk) {
console.log(a + ':' +b);
cbk();
}
function main() {
var cbk = function () {
if (z < data.length) {
main();
} else {
console.log('end');
}
z++;
}
some(data[z].a, data[z].b, cbk);
}
main();
Why is this an infinite loop?
jsFiddle Demo
There were a few things going on here that made the recursion fail involving the iteration control. By starting with z = 0, and comparing to .length, z will need to be pre-increased prior to the conditional check if( z < .length ).
The reason is that following the path of recursion, z is never incremented and so the recursion is infinite causing a lockout of the page. So, z needs to be handled before the recursive call takes place, preferably before the comparison to the .length.
In your original version, this was taking place not only after the if statement, but also after the recursive call. Fixing this iterator will fix your recursion.
if (++z < data.length) {
I was told to undelete this because it's answerable although I am gaining much hate, I found have noticed my mistake and did this.
var data = [{
a: 1,
b: 1
}, {
a: 2,
b: 2
}],
z = 0;
function some(a, b, cbk) {
console.log(a + ':' +b);
cbk();
}
function main() {
var cbk = function () {
z++;
if (z < data.length) {
main();
} else {
console.log('end');
}
}
some(data[z].a, data[z].b, cbk);
}
main();
I don't know how fluent at reading code you are, but I've tried to break down the concept of linear recursion into as generic a way as I could imagine
function recurse(data, /* fns */ step, worker, joiner, /* vals */ first, empty) {
function recursor(data, current) {
var result = worker(data, current), // do work with current iteration
next = step(data, current); // find the next iteration
if (next !== null) // if found
return joiner( // return
result, // the result from this time
recursor(data, next) // + the result from next time
);
else // if not found
return joiner( // return
result, // just this result
empty // this join is helpful for joining arrays/objects/etc
);
}
return recursor(data, first); // start it
}
So, an example based on what you were doing
var data = [{a: 1,b: 1}, {a: 2,b: 2}];
function init(data) {
function logger(data, i) { // a function describing what to do
var e = data[i]; // with this iteration
console.log(e.a + ':' + e.b);
return e.a;
}
function step(data, i) { // a function describing how to find
i = i + 1; // the next iteration
if (i < data.length) return i;
return null; // null = end
}
function add(a, b) { // a function describing how to join
return a + b; // two iterations together
}
return recurse(data, step, logger, add, 0, 0);
}
init(data); // run everything safely in it's own closure
/*
1:1
2:2
3 // === 1 + 2 + 0, from return of logger and result of add
*/
Of course in practice you could do a lot of this in-place rather than a function for each thing, and the step can usually be simplified so much that you don't need to var for result and next because you don't have to cache anything for an if test.