Javascript Functions within Array - javascript

Is there a way to print out the [ith] element of the array with the [ith] function's argument? for example, print out the returned value of 2nd element of the array with input (3) as function's argument
var puzzlers = [
function(a) { return 8 * a - 10; },
function(a) { return (a - 3) * (a - 3) * (a - 3); },
function(a) { return a * a + 4; },
function(a) { return a % 5; }
];

It's not exactly clear what you are looking for. I assume that you want to call the ith function passing j as an argument.
To access the ith element of an Array, you use the square brackets post-around-fix indexing operator [] and pass the index inside the square brackets, which looks like this: ary[idx]. To call a function, you use the round parentheses post-around-fix function call operator () and pass the argument inside the round parentheses, which looks like this: func(arg).
Like this:
puzzlers[2](3);
There's really nothing puzzling about this, if you understand what an array is and what a function is.

It sounds like you're looking for this, but the question is a bit cryptic.
var puzzlers = [
function(a) { return 8 * a - 10; },
function(a) { return (a - 3) * (a - 3) * (a - 3); },
function(a) { return a * a + 4; },
function(a) { return a % 5; }
];
var secondFunction = puzzlers[1];
var result = secondFunction(3);
alert(result);
//or short
alert(puzzlers[1](3));

Related

Assignement with parantheses in closure in d3 source code

While looking through the d3 source code, I found this snippet:
scale.unknown = function(_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
This implements the pattern here: https://bost.ocks.org/mike/chart/. Here's a minimal example that works, with the above code adapted:
function closure() {
let mult
function my(t) {
return t * mult
}
my.mult = function(_) {
return arguments.length ? (mult = _, my) : mult
}
return my
}
Afterwards, you can use it like this:
fn = closure()
fn.mult(2)
console.log(fn(3)) // 6
fn.mult(4)
console.log(fn(3)) // 12
What I don't understand in my above example is this line:
return arguments.length ? (mult = _, my) : mult
This checks if there are arguments, and assigns the parameter to mult if there are, or returns mult if there aren't.
But what does the parentheses mean in (mult = _, my)? What does putting the returned function at the very end do?
I believe you have actually two different questions here.
The first one is about the parenthesis: Bostock (D3 creator) did that to take advantage of the comma operator, which he commonly uses in his codes. In short, this...
return arguments.length ? (mult = _, my) : mult
Translates to: does the function has any passed argument? If no, return the value of mult; if yes, return the my function AND assign the passed parameter to mult.
Then you have a second question:
What does putting the returned function at the very end do?
Not much, because that's not necessary. The test of argument.length is just to use a getter, that is, returning the stored value if no argument is passed. It could be just:
return arguments.length ? mult = _ : mult;
You can check this here:
function closure() {
let mult
function my(t) {
return t * mult
}
my.mult = function(_) {
return arguments.length ? mult = _ : mult;
}
return my
}
fn = closure()
fn.mult(2)
console.log(fn(3))
fn.mult(4)
console.log(fn(3))
console.log("stored value: " + fn.mult())

looping through math operators using eval

var toyProblem = function () {
var sol= 0;
var operators = ['+','-','*','/'];
console.log(sol)
for(var i in arguments){
for(var j in operators){
sol = eval(sol + (operators[j]) + arguments[i]);
}
}
return sol;
}
toyProblem(6, 0, 10, 3); //6 + 0 - 10 * 3 === -12)
I'm trying to loop through 4 math operators for an unknown number of input values. I'm thinking of using eval in a nest for loop as a way of going through both the unknown number of arguments while also changing the math operator. At the bottom is the solution that I want to arrive at. Is this a good way of going about this problem or am I barking up the wrong tree?
var toyProblem = function () {
var sol_str='';
var operators = ['+','-','*','/'];
for(var i in operators){
var prev_operator=(i-1);
if(sol_str!=''){sol_str+=operators[prev_operator];}
sol_str +=arguments[i];
}
console.log(sol_str);
return eval(sol_str);
}
console.log(toyProblem(6, 0, 10, 3));
Nesting the 2 loops will result in doing 6 + 6 - 6 * 6 / 6 + 0 - 0 * 0 / 0 + 10 - 10 * 10 / 10 + 3 - 3 * 3 / 3
I didn't find a way to do this without eval as looping through operations one by one would modify the operators priority so this is what I propose : Building an operation 'query' to be eval'd and returned.
Hope this helps
var toyProblem = function () {
var operation = '';
var operators = ['+','-','*','/'];
var args = Array.from(arguments);
args.forEach(function (arg, index) {
if (index > 0) {
operation += operators[index - 1];
}
operation += arg;
});
return eval(operation);
}
console.log(6 + 0 - 10 * 3);
console.log(toyProblem(6, 0, 10, 3)); //6 + 0 - 10 * 3 === -24)
Let's decompose the problem. You have a variadic function that accepts unknown number of arguments and applies an operator to each next argument depending on the index of that element.
Because the number of arguments can be greater than the number of operators, it's appropriate to use modulo operator to infinitely loop through the array of operators while going once through the list of arguments.
The eval operation takes a string, evaluates it, and returns the result of evaluation of the expression that string represents. So you're on the right track. But because eval function takes a string as the first argument, I'd recommend using template literals, it's supported in almost all browsers natively and doesn't need to be transpiled into good old ES5.
The function then would look like this:
function toyProblem(first = 0, ...args) {
const operators = ['+', '-', '*', '/'];
let sol = first;
for (let i in args) {
sol = eval(`${sol} ${operators[i % operators.length]} ${args[i]}`);
}
return sol;
}
However, as there is recommended in the comments, using eval isn't something you'd like to ship to users. Instead, I'd suggest using functions. Functions in Javascript are first-class citizens, so you can pass them as an argument.
Imagine that you have a function (a, b) => a + b instead of just a string "+". The code would then look like this:
function toyProblem(first = 0, ...args) {
const operations = [
(a, b) => a + b,
(a, b) => a - b,
(a, b) => a * b,
(a, b) => a / b,
];
let sol = first;
for (let i in args) {
sol = operations[i](sol, args[i]);
}
return sol;
}
You could go even further and make the function universal in terms of possible operations. Have fun!
Since you are hard coding the names of the operators you might as well hard code the functions and avoid eval. You put the functions into an array that will let you loop through. Then you can just reduce through the arguments with a simple one-liner, which will handle any amount of arguments:
const op = [
(a, b) => a + b,
(a, b) => a - b,
(a, b) => a * b,
(a, b) => a / b
]
function prob(...args){
return args.reduce((curr, acc, idx) => op[(idx - 1) % op.length](curr, acc))
}
console.log(prob(6, 0, 10, 3))
console.log(prob(6, 0, 10, 3, 20, 11, 15, 100))
To get product -12 the first three parts of the expression need to be evaluated within parentheses, else the result will be -24. You can use String.prototype.replace() to replace "," characters after calling .toString() on input array, replace the "," with the operator, return the expression (6 + 0 - 10) * 3 from Function() constructor
var toyProblem = function () {
var operators = ['+','-','*'];
var opts = operators.slice(0);
var n = [...arguments];
var res = n.toString().replace(/,/g, () => opts.shift());
var index = res.indexOf(operators[operators.length -1]);
return new Function(`return (${res.slice(0, index)})${res.slice(index)}`)();
}
var product = toyProblem(6, 0, 10, 3);
console.log(product);

recursion factiorial. Why do I get NaN

I have this simple factorial function. It works on recursion. the number that I get at the end however is NaN. I am expecting an output of 6, factorial of 3. Is the problem because I defined x as a global variable ? and if so how do you define a variable as local inside the function without making it change in recursion.
var x;
function factorial(num)
{
if (num > 0) {
x = num * factorial(num - 1);
}
return x;
}
console.log(factorial(3));
If num > 0, you define x. What is x when num is not > 0?
HINT: Should be 1. Isn't. :)
HINT2: Try console.log(1 * undefined)
P.S.: Yes, var x should go inside the function. No, it doesn't do anything bad in this case, but it could.
You need to initialize x with value first.
var x = 1;
Let's investigate detaily what happened:
f(3) = 3 * f(2);
f(2) = 2 * f(1);
f(1) = 1 * f(0);
For f(0), it directly goes to return x;, while your global variable var x; is not initialized, thus f(0) return undefined, and 1 * factorial(0) get NaN, propagates to the final result.
One solution is not to use global variable:
function factorial(num)
{
var x = 1;
if (num > 0) {
x = num * factorial(num - 1);
}
return x;
}
console.log(factorial(3)); // 6

calling a function as data in D3.js

Im just getting started on d3.js and was going through Nick's source code on github here and got stuck at the part where he is passing a function as data into d3.js.
The var x in the function assigned to next var gets incremented from 0 to the loop counter as i show in the jsbin link below. I cant quite wrap my head around how x gets incremented automatically and how does it know the loop counter that it needs to get incremented upto everytime.
the next variable is called from >> newdata from the >>render function ?
I just setup a jsbin here
This part:
.data(newData);
is simply going to call the newData function and bind the return to the selection.
So each call to render in the setInterval simply pushes the next function into his data array.
This part then:
selection.attr("class", "v-bar")
.style("height", function (d, i) {
return d(i) + "px"; // <- E
})
.select("span")
.text(function(d, i){
return d(i); // <- F
});
Calls d which is the next function for each element in the data array. It's passing the index position in the data array.
So the first render call is:
15 + 0 * 0;
Second is:
15 + 0 * 0;
15 + 1 * 1;
Third is:
15 + 0 * 0;
15 + 1 * 1;
15 + 2 * 2;
First, for simplification, this
var selection = d3.select("#container").selectAll("div")
.data(newData); // <- D
is just like writing
var arrayOfFunctions = newData();
var selection = d3.select("#container").selectAll("div")
.data(arrayOfFunctions); // <- D
So, for example, calling this code 3 times (via setInterval) builds up arrayOfFunctions like this:
arrayOfFunctions = [
function (x) { return 15 + x * x; },
function (x) { return 15 + x * x; },
function (x) { return 15 + x * x; }
]
(Note: it's not literally like that, because in actuality they're just pointers to the same function next)
So nothing about that increments x. But once it binds those functions to DOM elements (via data(arrayOfFunctions) and runs through this bit:
selection.attr("class", "v-bar")
.style("height", function (d, i) {
return d(i) + "px"; // <- E
})
d is function (x) { return 15 + x * x; } and i (which is 0, 1, or 2) is passed in as x to that function when it calls d(i).
And that's what essentially increments x.

What is the initial value of an argument in a function within a function?

Using the code below:
function makeAddFunction(amount) {
function add(number) {
return number + amount;
}
return add;
}
var addTwo = makeAddFunction(2);
var addFive = makeAddFunction(5);
console.log(addTwo(1) + addFive(1));
The console prints out 9. I am assuming 'number' in the add function is zero but why is the value of 'number' initially 0?
There's no "initially 0" about this.
You're first returning a function that adds 2 to a number, then making a function that adds 5 to a number.
thus, you've effectively written:
console.log((2 + 1) + (5 + 1));
and 3 + 6 is 9.
addTwo is essentially:
var addTwo = function (number) {
return number + 2;
}
add addFive is:
var addFive = function (number) {
return number + 5;
}
because you're using this as a closure.
When you call makeAddFunction, it takes the parameter you passed in for amount and then returns that inner function.
Thus when you pass in 2, it returns this:
function add(number) {
return number + 2;
}
Then you are setting that code to the addTwo variable. So when you call addTwo with a parameter of 1, it returns 1+2 (3)

Categories