How can I access array in function composition created by reduce? [duplicate] - javascript

I came across this pattern in redux compose function. I still don't understand how in the example below the functions are evaluated starting from the last and not from the first:
function f2(a) {
return a + a;
}
function f3(a) {
return a + a + a;
}
function f4(a) {
return a + a + a + a;
}
function f5(a) {
return a + a + a + a + a;
}
function compose(...funcs) {
return funcs.reduce(function x(a, b) {
return function y(...args) {
const temp = a(b(...args));
return temp;
};
});
}
const composedFunction = compose(f2, f3, f4, f5);
const result = composedFunction(2);
In the first reduce iteration the accumulator is f2 so we'll get f2(f3(2))=12. In the next iteration we'll call f4(12)=48. In the last iteration we'll call f5(48)=240. So the evaluation order is f5(f4(f2(f3(2)))). But using console.log I see that the evaluation order is f2(f3(f4(f5(2)))) which is also 240 by coincidence.
As far as I understand the function y is called for all array elements so why only the last function gets 2 as the parameter?

Let's step through the code with a very simple example:
compose(f2, f3, f4)
As no initial value was passed to reduce, it will start with the first (f2) and the second (f3) value of the array and call the callback with that, x gets called with a being f2 and b being f3. Now x does'nt do anything, it just returns function y that can access a and b through a closure.
Reduce will now continue to the third element, the first argument being the result of the previous callback (the closured y), and the second argument being f4. Now x gets called again, and another closure is created over y, y gets the finally returned from the whole function.
If we try to visualize thus closured function it'll be:
y { // closure of y
a -> y { // a references another closure of y
a -> f3,
b -> f2
},
b -> f4
}
Now you call that closured y and pass 2 into it, that will call b (f4) and pass the result to the call to a (closured y).
a ( b(...args))
y { ... } ( f4(2) )
Now that closured y will do the same:
a ( b ( ...args))
f2( f3( f4( 2 ) ) )
Hint: It is sometimes really difficult to keep track of closured values, therefore the console provides you with great utilities to keep track of them: Open your code in the consoles "debugger" tab, click on the line numbers where the function calls are to attach breakpoints, then run the code again, the execution will yield whenever a breakpoint is reached and you can see the values of all variables (including closured ones).

The reduce is not calling the functions f2, f3, f3, f5, but it is creating a function from those. This is the value of the accumulator in each iteration. Note that the value is a function and not a result from execution of the function.
1:a=f2;b=f3;return value(NOT TEMP but function y)=f2(f3(...args))
2:a(prev return value)=f2(f3(...args));b=f4;return value=f2(f3(f4(...args)))
and so on....

The compose function can be re-written as:
function compose(...funcs) {
return funcs.reduce(function (a, b) {
return function (arg) {
const temp = a(b(arg));
return temp;
};
});
}
After the first iteration, the returned function which is passed in as the next accumulator is:
function (arg) { // R1
return f2(f3(arg));
}
After the second iteration, the returned function which is passed in as the next accumulator is:
function (arg) { // R2
return R1(f4(arg));
}
And finally, the returned function assigned to composedFunction is:
function (arg) { // composedFunction
return R2(f5(arg));
}
So running composedFunction(2) and going back up the chain:
f5(2) returns 10
R2(10) returns R1(f4(10))
which is R1(40)
R1(40) returns f2(f3(40))
which is f2(120)
which is 240
Hopefully that's sufficient.
It can be written as a single call as:
function composedFunction(arg) {
return f2(f3(f4(f5(arg))));
}

Related

Capturing an invoked function and its argument passed in as an argument

I am new to JavaScript and have several questions about functional programming.
Here is a statement:
outer(inner(5));
Is it possible to construct function outer in a way that allows it
to capture function inner and its argument 5?
Is it possible to construct function inner in a way that allows it to
pass itself and its argument 5 to function outer?
If the answer to both questions above is no, is it possible to
construct functions outer and inner in a way that allows the former
to capture function inner and its argument 5 or the
latter to pass itself and its argument 5 to function
outer?
I tried:
using the arguments object but to no avail.
function outer (parameter) {
return arguments;
}
function inner (n) {
return n + 1;
}
console.log(outer(inner(5))); // returns Arguments { 0: 6 ... }
using currying but I do not see how it can help me since I am not given the following statement:
outer()(5);
A possible workaround consists in returning an array from inner() composed of on one side the processing function and on the other side the argument.
outer will be able to access both by reading the array.
function outer(arr)
{
var fun = arr[ 0 ];
var arg = arr[ 1 ];
var result = fun(arg);
console.log('inner function is:', fun);
console.log('its argument is:', arg);
console.log('its result is:', result);
return result;
}
function inner(num)
{
return [
function (_num)
{
return _num + 1;
},
num
]
}
console.log(outer(inner(5)));
You could achieve this by letting your inner return a function (foo) which closes over n. You can then let foo return n+1. Then, within your outer function, you can invoke foo to get its return value:
const outer = f => f();
const inner = n => _ => n+1;
console.log(outer(inner(5)));
Alternatively, another possibility would involve changing your return value. You could return an array from inner which contains the original passed through arguments (...arguments) and the returned value (to_return) and then use destructuring assignment to get the passed in argument(s) (n & m) and the returned result:
function outer([result, n, m]) {
console.log("returned from inner: ", result);
console.log("arguments passed into inner: " + [n, m]);
return n;
}
function inner(n, m) {
let to_return = n + 1;
return [to_return, ...arguments];
}
console.log(outer(inner(5, 2))); // returns 5
Note: I added an m argument to demonstrate how you can extend this to multiple arguments
function outer(myFunction, argument) {
if (typeof myFunction !== "function") {
return false;
}
return myFunction(argument);
}
function inner(n) {
return n + 1;
}
console.log(outer(inner, 5));
Just a simple approach. Don’t execute the function inner but pass it as an argument (myFunction). And let the outer function execute it with the given argument.

How does a reference in closure and currying work in js?

The following program confuses me very much, the console.log() were added by me.
function add(a) {
console.log("1");
var total = a;
console.log("2");
var _fn = function (b) {
console.log("3");
total += b;
console.log("4");
return _fn;
};
console.log("5");
_fn.toString = _fn.valueOf = function () {
console.log("6");
return total;
};
console.log("7");
console.log("_fn: " + _fn);
return _fn;
}
When I ran add(1)(2), console showed:
1
2
5
7
6
_fn: 1
3
4
6
ƒ 3
My questions are:
1) in var _fn = function (b) {...}, what does _fn refer to in "return _fn" statement? If it refers to itself, then isn't it in infinite recursion like this
var _fn = function (b) {
total += b;
return function (b) {
total += b;
return function (b) {
total += b;
return _fn;
.
.
.
}
}
}
2) In console, it showed "_fn: 1" which means 1 was returned, but apparently, _fn (the function) was returned so that the calculation could keep going. So there is a conflict between the actual returned _fn and the value shown in console.
in var _fn = function (b) {...}, what does _fn refer to in "return _fn" statement?
The return statement says the when this function is called, the return value from the function will be (a reference to) the function object itself. Note it returns the function object, without calling it. Just the object, no call. At least not yet anyway....
If it refers to itself, then isn't it in infinite recursion like this ...
No, because the return value, the function, is not immediately called. It's kind of like doing this:
function g() {return g}
g()
Running that does not go into an infinite loop. You call the function g, and you get back g. You can do g()()()()()()() yourself, but that still "stops." Recursion is when a function calls itself, not returns itself!
In console, it showed "_fn: 1" which means 1 was returned, but apparently, _fn (the function) was returned so that the calculation could keep going. So there is a conflict between the actual returned _fn and the value shown in console.
Well, it's probably not correct to say 1 was returned; instead the code forces all console.logs (and similar) to produce the current value of total. At the time you did your console.log, total had the value of your first argument, namely 1. You were pretty smart to print out all those numbers, so it should help your understanding. Check out that after the 7 was printed, you had not yet done the subsequent call in which the addition was done. That's why you saw 1.

Trace the function 'thrice' - Function abstraction

I encountered the following code when I was doing my assignment. I can understand why the the expression (thrice(add1))(0) evaluates to 4. If we define f(x) = x + 1, (thrice(add1))(0) would be evaluated as f(f(f(x))) which is ((x+1)+1)+1. However, I don't quite understand why ((thrice(thrice))(add1))(0) would evaluate to 27, instead of 3*3=9.
//Javascript
function thrice(f) {
return compose(compose(f, f), f);
}
function compose(fun,fun2) {
return function (n) {
return fun(fun2(n));
};
}
function add1(k) {
return k + 1;
}
console.log(((thrice(thrice))(add1))(0)); //27
console.log((thrice(add1))(0)); //3
Inner (thrice):
thrice(1) returns ---> function (n) { return fun(fun2(n));
Outer (thrice):
thrice(1) returns ---> function (n) { return fun(fun2(n));
thrice(1) returns ---> function (n) { return fun(fun2(n));
thrice(1) returns ---> function (n) { return fun(fun2(n));
Outer (add1) introduces the add1 function to the scope.
When the 0's declared, add1 inserts it as k.
The add1 function resolves.
K's now one.
We're now back into the original ()'s.
The variable n's now equal to one.
The function2 or (fun2) becomes add1.
Then outer 'fun' becomes add1.
The whole return of one thrice=3.
The first time the outer thrice happens, the inner thrice returns the three.
The second time it iterates, it's three * three.
Finally with the last time, it's nine * three.

How can a function manipulate parameters passed via another function? Javascript

Sorry, first attempt at explaining this question was poor. Trying to learn Javascript and a question from a code problem (codewars) has me stumped. It states, write a function that takes another function as a parameter and caches results so that if the same parameters are sent then the return is pulled from the cache and the actual function is not invoked again. For example:
var x = function(a, b) { a * b };
var cachedFunction = cache(x);
cachedFunction(4, 5); // function x should be executed
cachedFunction(4, 5); // function x should not be invoked again, instead the cached result should be returned
cachedFunction(4, 6); // should be executed, because the method wasn't invoked before with these arguments
I am not sure how to access the arguments sent via cachedFunction. The goal is to write cache so that it can handle a function x with any number of arguments.
What you're describing is not possible.
The expression x(5, 4) is evaluated before the cache() function is even called. It's not receiving a function. It's receiving the value 20.
In your example, cache only has access to the return value of x. It can't know anything about how this return value was computed (i. e. by calling x with parameters 5, 4).
You would need to separately pass the function and its parameters to the cache function, e. g. as follows:
function cache(func, ...params) {
// Todo: do something with params
return func(...params);
}
function x(a, b){
return a * b;
}
console.log(cache(x, 5, 4));
you can return a table like this:
function x(a,b){
return [a, b, a*b];
}
after that you can get the params like this:
var result=x(values1,value2);
console.log(result[0]);// a == value1
console.log(result[1]);// b == value2
console.log(result[2]);// a*b == value1*value2

How to make a for loop wait until callback respond with value

I have click event which calls FireCallBackEvents and from there I pass the array of function which all are callback. Now I want to call function b() after function a() which gives the result of callback I call through setTimeout(). I expect that it will delay in giving result.
Now in below code alert of first function callback is called after function b and c is called.
This is only a sample of my real code.
function FireCallBackEvents(){
generalizeCallBack([a,b,c]);
}
function a(parameter1, parameter2,callback){
alert("Hello World: " + parameter1 + " : " + parameter2);
setTimeout(function(){callback("12")},600);
}
function b(parameter1, parameter2,callback){
alert("Hello World1: " + parameter1 + " : " + parameter2);
callback("123");
}
function c(parameter1, parameter2, callback){
alert("Hello World2: " + parameter1 + " : " + parameter2);
callback("1234");
}
function generalizeCallBack(arrayOfFunctions){
for(var i = 0; i < arrayOfFunctions.length; i++){
arrayOfFunctions[i]("1","2",function(we){
alert(we);
});
}
}
You could use this variant of your last function, which calls it recursively from the callback function you pass:
function generalizeCallBack(arrayOfFunctions){
if (!arrayOfFunctions.length) return; // nothing to do
var func = arrayOfFunctions.shift(); // extract function to execute
func("1","2", function(we){
alert(we);
generalizeCallBack(arrayOfFunctions); // recurse with shorter array
});
}
Note that this changes the array you pass. If you prefer that the callers keep their array in tact, use slice and not shift:
function generalizeCallBack(arrayOfFunctions){
if (!arrayOfFunctions.length) return; // nothing to do
var func = arrayOfFunctions[0]; // get function to execute
func("1","2", function(we){
alert(we);
generalizeCallBack(arrayOfFunctions.slice(1)); // recurse with shorter array
});
}
Since this version takes an array copy at every (recursive) call, we could make it more efficient by only doing that the first time (as suggested by #Alnitak):
function generalizeCallBack(arrayOfFunctions){
function recurse (arrayOfFunctions) {
if (!arrayOfFunctions.length) return; // nothing to do
var func = arrayOfFunctions.shift(); // extract first function
func("1","2", function(we){
alert(we);
recurse(arrayOfFunctions); // recurse with shorter array
});
}
// take copy (slice) of array in order not to alter the caller's array:
recurse(arrayOfFunctions.slice(0));
}
This way only one copy is taken of the array. The recursive part works on that same copy, making it shorter as it goes down the recursion chain.
This is the same, but written as an immediately invoked function expression:
function generalizeCallBack(arrayOfFunctions){
(function recurse (arrayOfFunctions) {
if (!arrayOfFunctions.length) return; // nothing to do
var func = arrayOfFunctions.shift(); // extract first function
func("1","2", function(we){
alert(we);
recurse(arrayOfFunctions); // recurse with shorter array
});
// take copy (slice) of array in order not to alter the caller's array:
}(arrayOfFunctions.slice(0)));
}
You should not call your array of functions within a loop in your generalizeCallBack function. It wouldn't help you delaying later functions (function b and c) from being executed based on the result of an early function (function a) which calls setTimeout.
The setTimeout function will only be executed when the browser gets next breathing space. That is right after your function loop.
The solution is to let your function a return a promise and execute other functions (b and c) when the promise is successful.

Categories