I'm working on Lambda Expression in Javascript and I wrote the following code:
var succRender = (x) => 'succ('+ x + ')';
var numerify = expr => ((expr)(succRender) (0));
var ZERO = f => x => (x) ;
var ONE = f => x => (f(x));
var TWO = f => x => (f(f(x)));
var THREE = f => x => (f(f(f(x))));
var PLUS = n => m => f => z => (n(f) (m(f)(z))) ;
When I call:
console.log(numerify((PLUS) (TWO) (THREE)));
the console replies correctly
succ(succ(succ(succ(succ(0)))))
But I've called:
console.log(numerify((PLUS) (TWO) (THREE)));
and
var PLUS = n => m => f => z => (n(f) (m(f)(z))) ;
has four parameters....
How Javascript really works to perform this situation? Which are the "values" of f and z in the call? And how Javascript retrieves those value two complete the task?
thanks in advance
Ed
Lets evaluate it step by step:
PLUS(TWO)
that calls the first function and passes TWO as n, it evaluates to:
m => f => z => (n(f) (m(f)(z)))
Then that is called with (THREE), so m is THREE, it evaluates to:
f => z => (n(f) (m(f)(z)))
Now numerify(...) gets called with expr being the line above, and inside the function it is:
expr(succRender)(0)
So it calls the function with f being succRender and z being 0. Now we can evaluate the PLUS body, so this:
n(f) (m(f)(z))
becomes:
TWO(succRender) (THREE(succRender)(0))
Now the TWO call gets evaluated, with succRender being f and the line above results in
(x => (f(f(x)))) (THREE(succRender)(0))
The same happens with THREE:
(x => f(f(x)))) ((x => (f(f(f(x)))))(0))
Now the right arrow function gets evaluated as ut gets called with (0) so x is 0
(x => f(f(x))) (f(f(f(0))))
So now succRender (f) gets called three times with the redult of the previous call:
(x => f(f(x))) ("succ(succ(succ(0)))")
Now the last arrow function gets evaluated and succRender gets called two times again:
"succ(succ(succ(succ(succ(0)))))"
Let's unpack things a bit to see what is happening more clearly. I've re-written PLUS as a simpler function that still takes four parameters but just adds them together.
var PLUS = a => b => c => d => a + b + c + d;
var intermediateResult = (PLUS)(1)(2); //the parenthesis around PLUS are actually not needed
console.log("intermediateResult", intermediateResult);
var secondIntermediateResult = intermediateResult(3);
console.log("secondIntermediateResult", secondIntermediateResult);
var finalResult = intermediateResult(3)(4);
console.log("finalResult", finalResult);
As you can see, if you only pass the first two parameters, you get a function back. You need to "fill in" all values in order to get the result.
Now, let's break down what happens in your code:
(PLUS) (TWO) (THREE)
As I mentioned, the parenthesis around PLUS are not needed. They don't do anything. So I'll re-write what's happening here:
var firstIntermediateResult = PLUS(TWO);
var secondIntermediateResult = firstIntermediateResult(THREE);
So, you are passing the first two parameters.
numerify((PLUS) (TWO) (THREE))
If we substitute with the breakdown from before, this is equivalent to
numerify(secondIntermediateResult)
So, let's look at the numerify function:
var numerify = expr => ((expr)(succRender) (0));
it takes a parameter called expr, then passes succRender to it. This is another function but it doesn't matter in terms of understanding the call sequence. From above we see that will return another function that takes one final parameter before returning a result and that parameter is 0, so re-written the result of your program is:
var thirdIntermediateResult = secondIntermediateResult(succRender);
var finalResult = thirdIntermediateResult(0);
So, the final form of PLUS after all arguments are supplied looks like this
n(f) (m(f)(z)) --> TWO(succRender)(THREE(succRender)(0))
Related
I just want to know how reduce works in the case of code below(which was provided by a stackoverflow user in my previous question, i'm asking this question as his code snippet led to me having more questions that weren't cleared up and are too long to fit in a comment section). An array of functions is passed into a reducer. There is a compose function which runs on the array of functions. From my understanding of this f is the accumulator and g is the next item in the array. What is returned each cycle of the reduce becomes the accumulator for the next cycle. If there is no initalValue parameter passed into reduce then the first item in the array will be used as the initial accumulator value.
const compose = (f, g, i) => (...args) => {
console.log(i, g);
console.log(i, f);
return f(g(...args));
}
const f_xe = (x) => x + 'e',
f_xd = (x) => x + 'd',
f_xc = (x) => x + 'c',
f_xy = (x, y) => x + y;
console.log([f_xe, f_xd, f_xc, f_xy].reduce(compose)('a','b'));
// 3 [Function: f_xy]
// 3 [Function]
// 2 [Function: f_xc]
// 2 [Function]
// 1 [Function: f_xd]
// 1 [Function: f_xe]
// abcde
I visualize it like this:
cycle #1:
f = f_xe
g = f_xd
return f(g(...args))
^ which is f_xe(f_xd('a', 'b'))
cycle #2:
f = what was returned previously
^^ which will be f_xe(f_xd('a', 'b'))
g = f_xc
return f(g(...args))
^^ which is f_xe(f_xd('a', 'b'))(f_xc('a', 'b'))
I already know this line of thinking is wrong the way the flow works it works in an encapsulating manner, like so: f_xe(f_xd((f_xc(f_xy('a', 'b')))))
but why is this the case. If someone can intricately explain why it wraps this way and break down each cycle of the reduce step by step it would be immensely appreciated. Another thing I was wondering is, why doesn't f just try to evaluate immediately on the first cycle? f_xe(f_xd('a', 'b')) when this piece of code is returned wouldn't it try to evaluate that and produce an error instead of proceeding to the next item in the array? Instead the code starts evaluating from the last item in the array even though the compose function is instructed to be applied from the beginning. Which I do understand as with a composition function the last item will be ran first and then so on, however shouldn't the console log statements be ran in the order of first to last?
Again, I know my line of thinking is completely off with this one, but I was hoping if I shared my train of thought someone could push it in the right direction. Thank you to anyone who can shed some light on this.
Forget about the 'a' and 'b' arguments first. The important part is
const f = [f_xe, f_xd, f_xc, f_xy].reduce(compose);
This is what we need to look at, and where we can apply our definition of reduce for. The call of f('a','b') comes later.
When expanding the reduce call, we find
const f = compose(compose(compose(f_xe, f_xd, 1), f_xc, 2), f_xy, 3);
(This is a bit weird actually. I'd recommend using reduceRight for composing functions. Also pass the identify function as the initial value for the accumulator.)
Now we can expand the compose calls:
const f1 = (...args) => {
console.log(1, f_xe);
console.log(1, f_xd);
return f_xe(f_xd(...args));
}
const f2 = (...args) => {
console.log(2, f1);
console.log(2, f_xc);
return f1(f_xc(...args));
}
const f3 = (...args) => {
console.log(3, f2);
console.log(3, f_xy);
return f2(f_xy(...args));
}
const f = f3;
Now when you call f3('a', 'b'), you can see why the logs happen "backwards".
shouldn't the console log statements be ran in the order of first to last?
If you want that, you maybe better put them in the compose function and not in the closure that it returns. Try with
const compose = (f, g, i) => {
console.log(i, g);
console.log(i, f);
return (...args) => f(g(...args));
}
Can somebody explain to me how Array.reduce can put functions as arguments in function composition like this:
const composeB = (f, g) => x => f(g(x))
const add = a => b => a + b
const add5 = add(5)
const double = a => a * 2
const add5ThenDouble = [double, add5].reduce(composeB)
console.log(add5ThenDouble(6)); // 22
So, according to my knowledge (which is not enough) of reduce function is that Array.reduce iterate through an array like this - it takes each of array values and puts them through callback function with another argument (lets call it accumulator). The next array value will undergo the same callback function, but with (eventually) changed accumulator value.
What confuses me in code example above is:
1) Array is list of functions [double, add5].
2) In first iteration, composeB will receive arguments: f=accumulator (empty value), g=double(function). ComposeB should return emptyvalue(double(6)) (or maybe not??)
I know that I am missing something, but can someone explain me what?
The documentation for reduce says that the first argument is
A function to execute on each element in the array (except for the first, if no initialValue is supplied).
So in this case, you have not supplied an initialValue and so compose is only called once (with arguments double and add5).
var inc = (x) => ++x, // increment +1
x2 = (x) => x*2, // multiply by 2
sq = (x) => x*x; // square
var compose = (f,g) => (_) => g(f(_));
var f1 = [ sq, inc, inc ].reduce(compose, (_) => _);
f1(10); // 102
var f2 = [ inc, sq, inc ].reduce(compose, (_) => _);
f2(10); // 122
See the code above, notice:
identity function (_) => _ as default value (second argument) for reduce
compose will NOT return a number, it will return a FUNCTION that is a composition of all the functions that were passed in before... So - only when you CALL the (say) f1, only then the functions will be executed.
we are putting all the functions from list [a,b,c,d,e] into a chain of e,d,c,b,a (reverse order!) and then execute as e(d(c(b(a(10))))) getting the order we actually wanted.
(f,g) => (_) => g(f(_)) <-- function arguments are actually reversed when calling them. Longer version: function compose (f, g) { return function (z) { return g(f(z)); }; }
p.s.: i use var because i can ;)
What does this function return? I'm not familiar with this nomenclature.
let x = 2;
let y = 8;
const a = function(b) { return function(c) { return x + y + Math.abs(b) + c; } };
// Statement will go here
const fn = a(x);
For the above function, I understand the x+y part, but what is the b and c referred to in the second half? Is a(x) calling const a?
The only thing I found that refers to similar nomenclature is function x y a b in javascript, but the discussion doesn't talk about how to find what is returned. Maybe I'm not searching for the right thing and that's why my search only returned one thing that is similar.
a is the result of a function that accepts an argument, b. That function returns another function that accepts an argument c and returns x + y + c plus absolute value of b.
let x = 2;
let y = 8;
const a = function(b) {
console.log({
b
});
return function(c) {
console.log({
c
});
return x + y + Math.abs(b) + c;
}
};
// Statement will go here
const fn = a(x);
fn(12) // will have b=2 and c=12
It seems like a function pointer. function(b) accepts the parameter x that was passed into the function pointer a, this function pointer references function(b) but unlike normal functions which immediately returns a value, function(b) returns another function function(c) which ofcourse accepts one parameter and that parameter should be filled out when const fn was invoked.
My theory is that when you call fn for example fn(3) then you will get a result equivalent to 2 + 8 + Math.abs(2) + 3;
Without const fn you could also invoke a like a(2)(3) which I believe will yeild the same result.
Hope this helps.
What you see here is called currying, something related, but different from partial application.
The point is to break down a function call taking multiple arguments into multiple function calls taking single arguments.
In this case, a is a function that returns a function that returns the result of adding x, y, the absolute of b (coming from the call to a) and c (coming from the call to the return value of a).
I am trying to write a simple compose function that takes a series of functions, and composes them like so:
compose(func1, func2, func3)(n) === func1(func2(func3(n)))
I do so by recursing through a rest parameter,
var compose = function(...args) {
return (n) => {
if (args.length) {
return args[0](compose(args.slice(1)));
} else {
return n;
}
};
};
I then attempt to compose a new function made up of a series of other functions,
var plusOneAndTwo = compose((n) => n + 1, (n) => n + 2);
plusOneAndTwo(1);
Instead of returning 4, I get back the body of the inner, anonymous function inside of compose as a string,
"(n) => {
if (args.length) {
return args[0](compose(args.slice(1)));
} else {
return n;
}
}1"
Note the "1" at the end of the string! I have no idea why this is happening, and in particular I'm perplexed by how a 1 is getting appended to the end of that.
Any clarification is appreciated, thanks!
The problem occurs in the recursive call to compose.
In particular, you are not passing the parameter n to it (as also suggested by others above). Furthermore, you need to expand the rest parameter in the call.
You should use something like:
return args[0](compose(...args.slice(1))(n))
In your case, you are simply returning:
return args[0](compose(args.slice(1)));
In your example you call compose((n) => n + 1, (n) => n + 2);. Compose then returns a function taking n as a parameter. In this function, args.length becomes 1 (i.e. true-is), args[0] becomes (n) => n + 1 and args.slice(1) becomes [(n) => n + 2].
Next, you call this returned function with the parameter n = 1. As args.length is 1, the if() statement will go into the if() case. In this if case, it will call args[0] with the argument compose(args.slice(1)).
In this recursive call, compose(args.slice(1)) is evaluated to a function, taking n as a parameter and the same function body.
This function is then given as the parameter n to args[0] (in the outer call). Recall that args[0] in this scenario is the function (n) => n + 1.
Thus the call as a whole is equivalent to:
// returned from the recursive call to compose(args.slice(1))
var n = (n) => {
if (args.length) {
return args[0](compose(args.slice(1)));
} else {
return n;
}
}
// applied to arg[0] == (n) => n + 1
return n + 1
This means that the code will attempt to add a function with the number 1.
In JavaScript adding a function and a number results in both objects coerced into a string. Casting a number into a string is trivial, casting a function into a string returns the function source code. These strings are then added to give the return value you saw: The function body as a string with the 1 at the end.
You just have to call the composed function:
return args[0](compose(...args.slice(1))(n));
Or without recursion it'll be:
const compose = (...fns) => start => fns.reduceRight((acc, fn) => fn(acc), start);
You could take a different approach by returning a new function or returning the last function for calling with arguments.
const
compose = (...fns) => fns.length
? v => compose(...fns.slice(0, -1))(fns.pop()(v))
: v => v,
fn1 = n => n * 5,
fn2 = n => n + 2,
fn3 = n => n * 7;
console.log(fn1(fn2(fn3(1))));
console.log(compose(fn1, fn2, fn3)(1));
Arrow functions in ES6 do not have an arguments property and therefore arguments.callee will not work and would anyway not work in strict mode even if just an anonymous function was being used.
Arrow functions cannot be named, so the named functional expression trick can not be used.
So... How does one write a recursive arrow function? That is an arrow function that recursively calls itself based on certain conditions and so on of-course?
Writing a recursive function without naming it is a problem that is as old as computer science itself (even older, actually, since λ-calculus predates computer science), since in λ-calculus all functions are anonymous, and yet you still need recursion.
The solution is to use a fixpoint combinator, usually the Y combinator. This looks something like this:
(y =>
y(
givenFact =>
n =>
n < 2 ? 1 : n * givenFact(n-1)
)(5)
)(le =>
(f =>
f(f)
)(f =>
le(x => (f(f))(x))
)
);
This will compute the factorial of 5 recursively.
Note: the code is heavily based on this: The Y Combinator explained with JavaScript. All credit should go to the original author. I mostly just "harmonized" (is that what you call refactoring old code with new features from ES/Harmony?) it.
It looks like you can assign arrow functions to a variable and use it to call the function recursively.
var complex = (a, b) => {
if (a > b) {
return a;
} else {
complex(a, b);
}
};
Claus Reinke has given an answer to your question in a discussion on the esdiscuss.org website.
In ES6 you have to define what he calls a recursion combinator.
let rec = (f)=> (..args)=> f( (..args)=>rec(f)(..args), ..args )
If you want to call a recursive arrow function, you have to call the recursion combinator with the arrow function as parameter, the first parameter of the arrow function is a recursive function and the rest are the parameters. The name of the recursive function has no importance as it would not be used outside the recursive combinator. You can then call the anonymous arrow function. Here we compute the factorial of 6.
rec( (f,n) => (n>1 ? n*f(n-1) : n) )(6)
If you want to test it in Firefox you need to use the ES5 translation of the recursion combinator:
function rec(f){
return function(){
return f.apply(this,[
function(){
return rec(f).apply(this,arguments);
}
].concat(Array.prototype.slice.call(arguments))
);
}
}
TL;DR:
const rec = f => f((...xs) => rec(f)(...xs));
There are many answers here with variations on a proper Y -- but that's a bit redundant... The thing is that the usual way Y is explained is "what if there is no recursion", so Y itself cannot refer to itself. But since the goal here is a practical combinator, there's no reason to do that. There's this answer that defines rec using itself, but it's complicated and kind of ugly since it adds an argument instead of currying.
The simple recursively-defined Y is
const rec = f => f(rec(f));
but since JS isn't lazy, the above adds the necessary wrapping.
Use a variable to which you assign the function, e.g.
const fac = (n) => n>0 ? n*fac(n-1) : 1;
If you really need it anonymous, use the Y combinator, like this:
const Y = (f) => ((x)=>f((v)=>x(x)(v)))((x)=>f((v)=>x(x)(v)))
… Y((fac)=>(n)=> n>0 ? n*fac(n-1) : 1) …
(ugly, isn't it?)
A general purpose combinator for recursive function definitions of any number of arguments (without using the variable inside itself) would be:
const rec = (le => ((f => f(f))(f => (le((...x) => f(f)(...x))))));
This could be used for example to define factorial:
const factorial = rec( fact => (n => n < 2 ? 1 : n * fact(n - 1)) );
//factorial(5): 120
or string reverse:
const reverse = rec(
rev => (
(w, start) => typeof(start) === "string"
? (!w ? start : rev(w.substring(1), w[0] + start))
: rev(w, '')
)
);
//reverse("olleh"): "hello"
or in-order tree traversal:
const inorder = rec(go => ((node, visit) => !!(node && [go(node.left, visit), visit(node), go(node.right, visit)])));
//inorder({left:{value:3},value:4,right:{value:5}}, function(n) {console.log(n.value)})
// calls console.log(3)
// calls console.log(4)
// calls console.log(5)
// returns true
I found the provided solutions really complicated, and honestly couldn't understand any of them, so i thought out a simpler solution myself (I'm sure it's already known, but here goes my thinking process):
So you're making a factorial function
x => x < 2 ? x : x * (???)
the (???) is where the function is supposed to call itself, but since you can't name it, the obvious solution is to pass it as an argument to itself
f => x => x < 2 ? x : x * f(x-1)
This won't work though. because when we call f(x-1) we're calling this function itself, and we just defined it's arguments as 1) f: the function itself, again and 2) x the value. Well we do have the function itself, f remember? so just pass it first:
f => x => x < 2 ? x : x * f(f)(x-1)
^ the new bit
And that's it. We just made a function that takes itself as the first argument, producing the Factorial function! Just literally pass it to itself:
(f => x => x < 2 ? x : x * f(f)(x-1))(f => x => x < 2 ? x : x * f(f)(x-1))(5)
>120
Instead of writing it twice, you can make another function that passes it's argument to itself:
y => y(y)
and pass your factorial making function to it:
(y => y(y))(f => x => x < 2 ? x : x * f(f)(x-1))(5)
>120
Boom. Here's a little formula:
(y => y(y))(f => x => endCondition(x) ? default(x) : operation(x)(f(f)(nextStep(x))))
For a basic function that adds numbers from 0 to x, endCondition is when you need to stop recurring, so x => x == 0. default is the last value you give once endCondition is met, so x => x. operation is simply the operation you're doing on every recursion, like multiplying in Factorial or adding in Fibonacci: x1 => x2 => x1 + x2. and lastly nextStep is the next value to pass to the function, which is usually the current value minus one: x => x - 1. Apply:
(y => y(y))(f => x => x == 0 ? x : x + f(f)(x - 1))(5)
>15
var rec = () => {rec()};
rec();
Would that be an option?
Since arguments.callee is a bad option due to deprecation/doesnt work in strict mode, and doing something like var func = () => {} is also bad, this a hack like described in this answer is probably your only option:
javascript: recursive anonymous function?
This is a version of this answer, https://stackoverflow.com/a/3903334/689223, with arrow functions.
You can use the U or the Y combinator. Y combinator being the simplest to use.
U combinator, with this you have to keep passing the function:
const U = f => f(f)
U(selfFn => arg => selfFn(selfFn)('to infinity and beyond'))
Y combinator, with this you don't have to keep passing the function:
const Y = gen => U(f => gen((...args) => f(f)(...args)))
Y(selfFn => arg => selfFn('to infinity and beyond'))
You can assign your function to a variable inside an iife
var countdown = f=>(f=a=>{
console.log(a)
if(a>0) f(--a)
})()
countdown(3)
//3
//2
//1
//0
i think the simplest solution is looking at the only thing that you don't have, which is a reference to the function itself. because if you have that then recusion is trivial.
amazingly that is possible through a higher order function.
let generateTheNeededValue = (f, ...args) => f(f, ...args);
this function as the name sugests, it will generate the reference that we'll need. now we only need to apply this to our function
(generateTheNeededValue)(ourFunction, ourFunctionArgs)
but the problem with using this thing is that our function definition needs to expect a very special first argument
let ourFunction = (me, ...ourArgs) => {...}
i like to call this special value as 'me'. and now everytime we need recursion we do like this
me(me, ...argsOnRecursion);
with all of that. we can now create a simple factorial function.
((f, ...args) => f(f, ...args))((me, x) => {
if(x < 2) {
return 1;
} else {
return x * me(me, x - 1);
}
}, 4)
-> 24
i also like to look at the one liner of this
((f, ...args) => f(f, ...args))((me, x) => (x < 2) ? 1 : (x * me(me, x - 1)), 4)
Here is the example of recursive function js es6.
let filterGroups = [
{name: 'Filter Group 1'}
];
const generateGroupName = (nextNumber) => {
let gN = `Filter Group ${nextNumber}`;
let exists = filterGroups.find((g) => g.name === gN);
return exists === undefined ? gN : generateGroupName(++nextNumber); // Important
};
let fg = generateGroupName(filterGroups.length);
filterGroups.push({name: fg});