What is going on with this JavaScript code? - javascript

Sorry I am new to Programming so I was unable to ask a more specific question. I find this code really confusing. I'm learning about callbacks.
function add(x, y, callback) {
callback(x + y)
}
function subtract(x, y, callback) {
callback(x - y);
}
function multiply(x, y, callback) {
callback(x * y);
}
function calculate(x, callback) {
callback(x);
}
calculate(5, (n) => {
add(n, 10, (n) => {
subtract(n, 2, (n) => {
multiply(n, 5, (n) => {
console.log(n); // 65
});
});
});
});

Essentially all this script does is the following ((5 + 10) - 2) * 5. Which returns the sum of 65. It just does that with extensive use of callbacks.
All function you have has a callback, this means each function can call a another function if that function is defined,. side note: otherwise it gives an error.
function subtract(x, y, callback) {
callback(x - y);
}
This function take in three values:
x equals A number
y equals The number that x will be minused with
callback = The function to run at the end
Let's just run that function and put in an anonymous function with a console.log
subtract(15, 2, function (x) {
console.log(x);
// x = 13
});
Let add another layer to that same function by calling it twice.
subtract(15, 2, function (x) {
subtract(x, 2, function (x) {
console.log(x);
// x = 11
});
});
That is how everything works, it is just nested functions over complicating basic math.

This is a JS callback example:
In JS, just like a value one can pass a function to another function;
So, if you want to simplify what is going on here, in the calling part -
var calculateVal = calculate(5); // result is 5
var addedVal = add(calculateVal, 10); // result is 15
var subtractVal = subtract(addedVal, 2); // result is 13
var multiplyVal = multiply(subtractVal, 5); // result is 65 ; your end resullt

Related

Only allowing a function to run n times with wrapper function

I need to make a wrapper function to invoke a function multiply with a given number num of times to allow the multiply to execute. nTimes(num,2) Then assign to runTwice -- runTwice can be any function that invoke the nTimes function which given a different num input--
In my case, for simplicity, I am only allowing it to run 2 times num=2
If we run the runTwice function the first time and the second time it will return the result of multiply function calculated with the inputs for multiply. Any invocation after the second time will not run the multiply function but will return the latest result of the multiply function.
Here is my implementation using an object to keep track of how many times we have execute the function, the max number allowed to execute and the latest result of multiply
'use strict'
//use a counter object to keep track of counts, max number allowed to run and latest result rendered
let counter = {
count:0,
max: 0,
lastResult: 0
};
let multiply = function(a,b){
if(this.count<this.max){
this.count++;
this.lastResult = a*b;
return a*b;
}else{
return this.lastResult;
}
}
// bind the multiply function to the counter object
multiply = multiply.bind(counter);
let nTimes=function(num,fn){
this.max = num;
return fn;
};
// here the nTimes is only executed ONE time, we will also bind it with the counter object
let runTwice = nTimes.call(counter,3,multiply);
console.log(runTwice(1,3)); // 3
console.log(runTwice(2,3)); // 6
console.log(runTwice(3,3)); // 6
console.log(runTwice(4,3)); // 6
Note that I have altered the simple multiply quite a bit and bind it the counterobject to make it work. Also using call on nTimes to bind counter object.
What can I do to implement the same result with a wrapper function but less alteration to the simple multiply function?
Let's say the multiply function is very simple:
let multiply = function(a,b){ return a*b };
You could use a closure over the count and the last value and check count and decrement and store the last result.
const
multiply = (a, b) => a * b,
maxCall = (fn, max, last) => (...args) => max && max-- ? last = fn(...args) : last,
mult3times = maxCall(multiply, 3);
console.log(mult3times(2, 3));
console.log(mult3times(3, 4));
console.log(mult3times(4, 5));
console.log(mult3times(5, 6));
console.log(mult3times(6, 7));
Nina's answer is great. Here's an alternative, with code that might look slightly easier to read:
function multiply(a, b) {
return a * b;
}
function executeMaxTimes(max, fn) {
let counter = 0, lastResult;
return (...args) => counter++ < max
? lastResult = fn(...args)
: lastResult;
}
const multiplyMaxTwice = executeMaxTimes(2, multiply);
console.log(multiplyMaxTwice(1, 3)); // 3
console.log(multiplyMaxTwice(2, 3)); // 6
console.log(multiplyMaxTwice(3, 3)); // 6
console.log(multiplyMaxTwice(4, 3)); // 6
Seeing how both Nina and Jeto have answered your question, here is a simple and similar way to do it that also keeps a history of all the results in case you want to get them at a later time.
function multiply(a, b) {
return a * b;
}
function runMaxNTimes(num, callBack) {
var results = new Array(num);
var callTimes = 0;
return function(...params) {
return results.length > callTimes ?
results[callTimes++] = callBack(...params) :
results[callTimes - 1];
};
}
var runTwice = runMaxNTimes(2, multiply);
console.log(runTwice(1, 3)); // 3
console.log(runTwice(2, 3)); // 6
console.log(runTwice(3, 3)); // 6
console.log(runTwice(4, 3)); // 6

How to combine functions in another FP?

I am learning function programming in JavaScript, currently I have the following code.
I would like to combine this two functions in another function which alllow an user to pass a value in and having the result equal to the value passed plus 10 multiply 3 using the following functions.
Pseudo code example:
const myFormulat= add(10).multiply(3);
How can I write this function using only vanilla JS ES6?
function add(x){
return function(y){
return y + x;
};
}
function multiply(x){
return function(y){
return y * x;
};
}
// my calculation
// get x add 10 and after multiply by 3
Bear traps and landmines
This answer exists solely to demonstrate why this is not such a great idea – complexity is thru the roof with basically no gain. Note we must tell our function when to end, so i've added a special function call so our expressions will look like this
.add(3).mult(4).call(x)
// where x is the input for the entire function chain
One last change is our library of functions add, mult, et al must be wrapped in some scope that limits the reach of our proxy. This scope tells us exactly where the functions we wish to chain exist.
Oh and if the title of this section wasn't a warning enough, we use a Proxy too.
// helpers
const identity = x => x
const comp = f => g => x => f(g(x))
// magic wand
const using = scope => {
let acc = identity
let p = new Proxy({
call: x => acc(x),
}, {
get: (target, name) => {
if (name in target)
return target[name]
else if (name in scope)
return x => {
acc = comp (scope[name](x)) (acc)
return p
}
else
throw Error(`${f} is not undefined in ${scope}`)
}
})
return p
}
// your functions wrapped in a scope
const math = {
add: x => y => x + y,
mult: x => y => x * y
}
// chain it up
const main = using(math).add(3).mult(4).add(5).mult(6).call
console.log(main(2))
// (((2 + 3) * 4) + 5) * 6
// ((5 * 4) + 5) * 6
// (20 + 5) * 6
// 25 * 6
// 150
Function composition
But seriously, don't do that. Pushing everything through the . operator is unnatural given your starting point and you should be looking for more effective means to combine functions.
We can effectively do the same thing using a slightly different notation – the biggest difference here is complexity is almost zero
const compose = (f,...fs) => x =>
f === undefined ? x : compose (...fs) (f(x))
const add = x => y => x + y
const mult = x => y => x * y
const main = compose (add(3), mult(4), add(5), mult(6))
console.log(main(2)) // => 150
Functors
Maybe you don't like traditional function composition, and that's fine, because we have yet another way to tackle this problem using Functors – simply put, a Functor is a container with a map function.
Below we have a Box function which puts values in our container. The map function accepts a function and creates a new Box with the return value of the user-specified function. Lastly, we have a fold function which allows us to take our value out of the box
Again, it changes up the way we write the code a little bit, but the reduction is complexity is tremendous (compared to the Proxy example)
const Box = x => ({
map: f => Box(f(x)),
fold: f => f(x)
})
const add = x => y => x + y
const mult = x => y => x * y
const main = Box(2).map(add(3)).map(mult(4)).map(add(5)).map(mult(6)).fold
main(console.log) // 150
See: http://scott.sauyet.com/Javascript/Talk/Compose/2013-05-22/
function add(x){
return function(y){
return y + x;
};
}
function multiply(x){
return function(y){
return y * x;
};
}
Function.prototype.compose = function(g) {
var fn = this;
return function() {
return fn.call(this, g.apply(this, arguments));
};
};
var f = multiply(3).compose(add(10));
console.log(f(5));
If i understand you correctly you are trying to figure out function chaining in JavaScript
Function Chaining or Method chaining is a common pattern in JS world.
one of the methods in which you can achieve chaining is by creating a class and returning this operator or current object reference back
You can find interesting tutorial regarding this in following URL
https://www.bennadel.com/blog/2798-using-method-chaining-with-the-revealing-module-pattern-in-javascript.htm

How to add parameters to a function argument without calling it

For example, addEventListener's 2-nd argument has a "e" or "evt" or "event" or "..." parameter. How can I add parameters to a function argument without calling it (without using arguments object). Is it possible?
Sorry for my bad english :)
You are looking for partial functions.
You can create functions with arguments and not provide them. For example,
function add(x, y) {
return x + y;
}
console.log(add(1, 2)); // 3
console.log(add(2)); // NaN (2 + undefined)
console.log(add(0)); // NaN (undefined + undefined)
If you don't want the function to return value like NaN, you can write this:
function add2(x, y) {
x = x || 0;
y = y || 0;
return x + y;
}
console.log(add2(1, 2)); // 3
console.log(add2(2)); // 2
console.log(add2(0)); // 0

Javascript Calculator Function: How does it work?

I'm going through some tutorials and saw this block of code that I can't figure out. Can someone walk me through it please? I don't understand how the return ultimately executes the variable function.
var plus = function(x,y){ return x + y };
var minus = function(x,y){ return x - y };
var operations = {
'+': plus,
'-': minus
};
var calculate = function(x, y, operation){
return operations[operation](x, y);
}
calculate(38, 4, '+');
calculate(47, 3, '-');
operations is an object that has + and - as keys, so by passing one of those to it you will get
operations['+'] = plus
Now, the brackets indicate a function call which can also be made via a variable as in this case. So translated the return statement is nothing more than
return plus(x,y);
var calculate = function(x, y, operation){
return operations[operation](x, y); // operations['+'] = plus
}
Which calls above method and returns the value returned by that method.
Explanation
Look at my comments for an explanation.
var plus = function(x,y){ return x + y }; //-- var plus contains this function now.
var minus = function(x,y){ return x - y };
var operations = {
'+': plus, //-- This states that '+' contains the plus function.
'-': minus //-- This states that '-' contains the minus function.
};
var calculate = function(x, y, operation){ //-- operation makes it able to select a function from operations.
return operations[operation](x, y);
}
calculate(38, 4, '+'); //-- The '+' selects the plus function here.
calculate(47, 3, '-'); //-- The '-' selects the minus function here.
Executions will be something like this:
First argument is being passed as a key of the object and respective function is executed with arguments..
var calculate=function(x, y, operation)
{
//operations['+'](38, 4);
//operations['-'](47, 3);
return operations[operation](x, y);
};

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.

Categories