I'm not able to call a named callback function - javascript

I'm having a hard time figuring out how to make a function and call it from another function as a callback. My code below has been butchered up for troubleshooting, but I was attempting to name as many of my functions as possible to make it cleaner. I have had some success by un-naming the functions and making them all anonymous inline.
I'm specifically confused by the declaration of variables inside the parenthesis of the function definition.
function pickRnd (err, res, pullQuestions) {
var i = 0;
var qSelects = new Array();
qSelects.k1 = Math.floor(Math.random() * res.n);
qSelects.k2 = Math.floor(Math.random() * res.n);
while ( qSelects.k2 == qSelects.k1 ) {
qSelects.k2 = Math.floor(Math.random() * res.n);
i++;
if (i == 20) {break;}
}
qSelects.k3 = Math.floor(Math.random() * res.n);
while ( qSelects.k3 == qSelects.k2 || qSelects.k3 == qSelects.k1 ) {
qSelects.k3 = Math.floor(Math.random() * res.n);
i++;
if (i == 40) {break;}
}
console.log('::' + qSelects.k1);
console.log('::' + qSelects.k2);
console.log('::' + qSelects.k3);
function pullQuestions(qSelects) {
console.log('function pullQuestions start');
var qArray = new Object();
db.records.findOne({}).skip(qSelects.k1, function(err, result) {
qArray.push(result);
});
db.records.findOne({}).skip(qSelects.k2, function(err, result) {
qArray.push(result);
});
db.records.findOne({}).skip(qSelects.k3, function(err, result) {
qArray.push(result);
});
console.log('2' + qArray);
};
}
module.exports = function(res) {
console.log(res);
db.records.runCommand('count', function (err, res) {
console.log(res);
console.log(res.n);
pickRnd(null, res);
});
}

You've declared a third argument to pickRnd and called it pullQuestions. But in your pickRnd body, you've also declared a function with the name pullQuestions.
When you call pickRnd, you aren't passing it three arguments, which suggests you don't want to list that third argument in the pickRnd arguments list.
But you don't actually call pullQuestions anywhere in your pickRnd function, so it doesn't make sense to declare it there.
I'm specifically confused by the declaration of variables inside the parenthesis of the function definition.
Those aren't variables, though they're similar to variables. They're arguments. They're things the function expects to receive from its caller when it's called. Simpler example:
function foo(a) {
console.log("a = " + a);
}
foo expects to receive an argument when you call it. foo will refer to that argument using the name a. So during this call:
foo(42);
...in the foo code, a will be 42.
In contrast, variables are normally internal to the function. For instance:
function foo(a) {
var b;
b = a * 2;
console.log("a = " + a);
console.log("b = " + b);
}
Now, foo expects to receive a single argument, which it calls a, and separately foo declares a local variable b that it will use internally.
Regarding calling named functions and/or callbacks, perhaps another simple example will help: Let's assume we have foo and foo will call a callback function we pass into it:
function foo(count, callback) {
var n;
for (n = 0; n < count; ++n) {
callback(n);
}
}
If we call foo, it will call the callback we give it count times with a number starting at 0 and increasing by one each time. So here's an anonymous function as a callback:
foo(5, function(x) {
console.log(x);
});
function foo(count, callback) {
var n;
for (n = 0; n < count; ++n) {
callback(n);
}
}
foo(5, function(x) {
snippet.log(x);
});
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Here's an example of a named function, bar, as the callback:
function bar(x) {
console.log(x);
}
foo(5, bar);
function foo(count, callback) {
var n;
for (n = 0; n < count; ++n) {
callback(n);
}
}
function bar(x) {
snippet.log(x);
}
foo(5, bar);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Related

Question of partialLeft and partialRight function

These partialLeft and partialRight functions are containing same things in body but it takes different return values.
Why did come this situation?
function partialLeft(f, ...outerArgs) {
return function(...innerArgs) { // Return this function
let args = [...outerArgs, ...innerArgs]; // Build the argument list
return f.apply(this, args); // Then invoke f with it
};
}
// The arguments to this function are passed on the right
function partialRight(f, ...outerArgs) {
return function(...innerArgs) { // Return this function
let args = [...innerArgs, ...outerArgs]; // Build the argument list
return f.apply(this, args); // Then invoke f with it
};
}
// The arguments to this function serve as a template. Undefined values
// in the argument list are filled in with values from the inner set.
function partial(f, ...outerArgs) {
return function(...innerArgs) {
let args = [...outerArgs]; // local copy of outerargs template
let innerIndex=0; // which inner arg is next
// Loop through the args, filling in undefined values from inner args
for(let i = 0; i < args.length; i++) {
if (args[i] === undefined) args[i] = innerArgs[innerIndex++];
}
// Now append any remaining inner arguments
args.push(...innerArgs.slice(innerIndex));
return f.apply(this, args);
};
}
// Here is a function with three arguments
const f = function(x,y,z) { return x * (y - z); };
// Notice how these three partial applications differ
partialLeft(f, 2)(3,4) // => -2: Bind first argument:
2 * (3 - 4)
partialRight(f, 2)(3,4) // => 6: Bind last argument:
3 * (4 - 2)
partial(f, undefined, 2)(3,4) // => -6: Bind middle argument: 3 * (2 - 4)
these partialLeft and partialRight functions are containing same things in body
No they aren't. First does
let args = [...outerArgs, ...innerArgs];
Second does
let args = [...innerArgs, ...outerArgs];
so their order is reversed.

How to write a function to evaluate this expression? [duplicate]

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

Unable to access changed variable value inside nested functions

I have a huge business logic to be executed in both of the below functions but I struck in one issue. I know its related to closure but how to solve I am not aware of. Can you through some light.
function func1() {
var x = false;
console.log('before going inside func '+x);
func2(x);
console.log('After coming outside => '+x);
//Instead of true its displaying false
}
function func2(x)
{
x = true;
console.log('inside func => '+ x);
}
func1();
My original problem is like below
function func1() {
var x = false;
var y =1;
var z=3;
func2(x,y,z);
console.log(x,y,z);
//INSTEAD OF true,10,30; its displaying false,1,3
}
function func2(x,y,z)
{
x = true;
y=10;
z=30;
}
func1();
The x parameter of func2 is completely distinct from the x variable in func1. When you do func2(x), the value of x is passed to func2, not some kind of reference to the variable. (Some languages do that; JavaScript does not.)
To return information out of a function, use return in the function, and use the function's return value where you call it:
function func1() {
var x = false;
console.log('before ' + x);
x = func2(x); // *** Note `x =`
console.log('after ' + x);
}
function func2(x) {
return true;
}
func1();
Perhaps a better example, using the value of x in func2:
function func1() {
var a = 1;
var b = 12;
console.log('a before: ' + a);
a = func2(a);
console.log('a after: ' + a);
console.log('b before: ' + b);
b = func2(b);
console.log('b after: ' + b);
}
function func2(x) {
return x * 2;
}
func1();
If you have complex information to return, return an object with properties for the complex information (or pass in an object, and have func2 fill in properties on it, it depends on the use case [and whether you're adhering to immutability paradigms]).

Javascript - function with arguments as another function's argument

I'm trying to pass a function with two arguments as an argument to another function (sort of callbacks). I have one function that is unchangeble ("F"), and another that's a wrapper to the former one, and which I can code the way I like ("G"). I tried to simplify the code as much as possible, leaving just the important parts of it:
"use strict"
// this function can't be changed in any way
var F = function (a, b)
{
return new G(function (success, error)
{
var sum = a + b;
if (sum > 0)
{
// EXCEPTION: point of failure, since we can't reach G.success
success(sum);
}
else
{
// of course we'd fail here too
error(sum);
}
});
};
var G = function (f)
{
this.success = function (result)
{
console.log("The sum is positive: " + result);
}
this.error = function (result)
{
console.log("The sum is negative: " + result);
}
return f();
};
var result = F(10, 5);

How to use a variable number of arguments in a JavaScript function

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.

Categories

Resources