How do I write an arrow function in ES6 recursively? - javascript

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});

Related

JavaScript Arrow Function and Closure problem

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))

Lodash FP Compose on Multiple parameters [duplicate]

import {flow, curry} from 'lodash';
const add = (a, b) => a + b;
const square = n => n * n;
const tap = curry((interceptor, n) => {
interceptor(n);
return n;
});
const trace2 = curry((message, n) => {
return tap((n) => console.log(`${message} is ${n}`), n);
});
const trace = label => {
return tap(x => console.log(`== ${ label }: ${ x }`));
};
const addSquare = flow([add, trace('after add'), square]);
console.log(addSquare(3, 1));
I started by writing trace2 thinking that trace wouldn't work because "How can tap possibly know about n or x whatever?".
But trace does work and I do not understand how it can “inject” the x coming from the flow into the tap call. Any explanation will be greatly appreciated :)
Silver Spoon Evaluation
We'll just start with tracing the evaluation of
addSquare(3, 1) // ...
Ok, here goes
= flow([add, trace('after add'), square]) (3, 1)
add(3,1)
4
trace('after add') (4)
tap(x => console.log(`== ${ 'after add' }: ${ x }`)) (4)
curry((interceptor, n) => { interceptor(n); return n; }) (x => console.log(`== ${ 'after add' }: ${ x }`)) (4)
(x => console.log(`== ${ 'after add' }: ${ x }`)) (4); return 4;
console.log(`== ${ 'after add' }: ${ 4 }`); return 4;
~log effect~ "== after add: 4"; return 4
4
square(4)
4 * 4
16
= 16
So the basic "trick" you're having trouble seeing is that trace('after add') returns a function that's waiting for the last argument. This is because trace is a 2-parameter function that was curried.
Futility
I can't express how useless and misunderstood the flow function is
function flow(funcs) {
const length = funcs ? funcs.length : 0
let index = length
while (index--) {
if (typeof funcs[index] != 'function') {
throw new TypeError('Expected a function')
}
}
return function(...args) {
let index = 0
let result = length ? funcs[index].apply(this, args) : args[0]
while (++index < length) {
result = funcs[index].call(this, result)
}
return result
}
}
Sure, it "works" as it's described to work, but it allows you to create awful, fragile code.
loop thru all provided functions to type check them
loop thru all provided functions again to apply them
for some reason, allow for the first function (and only the first function) to have special behaviour of accepting 1 or more arguments passed in
all non-first functions will only accept 1 argument at most
in the event an empty flow is used, all but your first input argument is discarded
Pretty weird f' contract, if you ask me. You should be asking:
why are we looping thru twice ?
why does the first function get special exceptions ?
what do I gain with at the cost of this complexity ?
Classic Function Composition
Composition of two functions, f and g – allows data to seemingly teleport from state A directly to state C. Of course state B still happens behind the scenes, but the fact that we can remove this from our cognitive load is a tremendous gift.
Composition and currying play so well together because
function composition works best with unary (single-argument) functions
curried functions accept 1 argument per application
Let's rewrite your code now
const add = a => b => a + b
const square = n => n * n;
const comp = f => g => x => f(g(x))
const comp2 = comp (comp) (comp)
const addSquare = comp2 (square) (add)
console.log(addSquare(3)(1)) // 16
"Hey you tricked me! That comp2 wasn't easy to follow at all!" – and I'm sorry. But it's because the function was doomed from the start. Why tho?
Because composition works best with unary functions! We tried composing a binary function add with a unary function square.
To better illustrate classical composition and how simple it can be, let's look at a sequence using just unary functions.
const mult = x => y => x * y
const square = n => n * n;
const tap = f => x => (f(x), x)
const trace = str => tap (x => console.log(`== ${str}: ${x}`))
const flow = ([f,...fs]) => x =>
f === undefined ? x : flow (fs) (f(x))
const tripleSquare = flow([mult(3), trace('triple'), square])
console.log(tripleSquare(2))
// == "triple: 6"
// => 36
Oh, by the way, we reimplemented flow with a single line of code, too.
Tricked again
OK, so you probably noticed that the 3 and 2 arguments were passed in separate places. You'll think you've been cheated again.
const tripleSquare = flow([mult(3), trace('triple'), square])
console.log(tripleSquare(2)) //=> 36
But the fact of the matter is this: As soon as you introduce a single non-unary function into your function composition, you might as well refactor your code. Readability plummets immediately. There's absolutely no point in trying to keep the code point-free if it's going to hurt readability.
Let's say we had to keep both arguments available to your original addSquare function … what would that look like ?
const add = x => y => x + y
const square = n => n * n;
const tap = f => x => (f(x), x)
const trace = str => tap (x => console.log(`== ${str}: ${x}`))
const flow = ([f,...fs]) => x =>
f === undefined ? x : flow (fs) (f(x))
const addSquare = (x,y) => flow([add(x), trace('add'), square]) (y)
console.log(addSquare(3,1))
// == "add: 4"
// => 16
OK, so we had to define addSquare as this
const addSquare = (x,y) => flow([add(x), trace('add'), square]) (y)
It's certainly not as clever as the lodash version, but it's explicit in how the terms are combined and there is virtually zero complexity.
In fact, the 7 lines of code here implements your entire program in less than it takes to implement just the lodash flow function alone.
The fuss, and why
Everything in your program is a trade off. I hate to see beginners struggle with things that should be simple. Working with libraries that make these things so complex is extremely disheartening – and don't even get me started on Lodash's curry implementation (including it's insanely complex createWrap)
My 2 cents: if you're just starting out with this stuff, libraries are a sledgehammer. They have their reasons for every choice they made, but know that each one involved a trade off. All of that complexity is not totally unwarranted, but it's not something you need to be concerned with as a beginner. Cut your teeth on basic functions and work your way up from there.
Curry
Since I mentioned curry, here's 3 lines of code that replace pretty much any practical use of Lodash's curry.
If you later trade these for a more complex implementation of curry, make sure you know what you're getting out of the deal – otherwise you just take on more overhead with little-to-no gain.
// for binary (2-arity) functions
const curry2 = f => x => y => f(x,y)
// for ternary (3-arity) functions
const curry3 = f => x => y => z => f(x,y,z)
// for arbitrary arity
const partial = (f, ...xs) => (...ys) => f(...xs, ...ys)
Two types of function composition
One more thing I should mention: classic function composition applies functions right-to-left. Because some people find that hard to read/reason about, left-to-right function composers like flow and pipe have showed up in popular libs
Left-to-right composer, flow, is aptly named because your eyes will flow in a spaghetti shape as your try to trace the data as it moves thru your program. (LOL)
Right-to-left composer, composer, will make you feel like you're reading backwards at first, but after a little practice, it begins to feel very natural. It does not suffer from spaghetti shape data tracing.

Finite number of recursions in Javascript with ES6 Y-combinator

I came across an answer to another SO question about recursion in Javascript, that gave a very terse form in ES6 using the Y-combinator, using ES6's fat arrow, and thought hey, that'd be neat to use - then 15 minutes or so later had circled back to hm, maybe not.
I've been to a few Haskell/Idris talks and run some code before, and familiar with standard JS, so was hoping I'd be able to figure this out, but can't quite see how a simple "do n recursions and return" is supposed to go, and where to implement a decrementing counter.
I just wanted to simplify getting the nth parent node of a DOM element, and there seem to be more dense explain-all guides than examples of simple applications like this.
The example I first saw is:
const Y = a => (a => a(a))(b => a(a => b(b)(a)));
while this more recent answer gives:
const U = f => f (f)
const Y = U (h => f => f (x => h(h)(f)(x)))
...which is given with examples of what the internal functions might be, and some example outputs, but introducing the U-combinator doesn't really help clarify this for me.
In the first example I can't really begin to understand what b might be in my case - I know I need one function a to return the parent node:
const par = function(node) {
return node.parentNode;
}
I came up with the below:
function RecParentNode(base_node, n) {
// ES6 Y-combinator, via: https://stackoverflow.com/a/32851197/2668831
// define immutable [const] functions `Y` and `fn` [`fn` uses `Y`]
// the arguments of `Y` are another two functions, `a` and `b`
const Y = par=>(par=>par(par))(b=>par(par=>b(b)(par)));
const fn = Y(fn => n => {
console.log(n);
if (n > 0) {
fn(n - 1);
}
});
}
but then couldn't see what to do with the spare b lying around, and was about to delete it all and just forget I bothered.
All I'd like is to apply the par function n times, since the only alternatives I'm aware of are chaining .parentNode.parentNode.parentNode... or cheating and turning a string into an eval call.
Hoping someone familiar with functional JS could help me get the idea here for how to use the Y-combinator to make this helper function RecParentNode - thanks!
due diligence
Hey, that answer you found is mine! But before looking at various definitions of the Y combinator, we first review its purpose: (emphasis mine)
In functional programming, the Y combinator can be used to formally define recursive functions in a programming language that doesn't support recursion (wikipedia)
Now, let's review your question
I just wanted to simplify getting the nth parent node of a DOM element, and there seem to be more dense explain-all guides than examples of simple applications like this.
JavaScript supports direct recursion which means functions can call themselves directly by name. No use of U or Y combinators is necessary. Now to design a recursive function, we need to identify our base and inductive case(s)
base case – n is zero; return the node
inductive case 1 – n is not zero, but node is empty; we cannot get the parent of an empty node; return undefined (or some error if you wish)
inductive case 2 - n is not zero and node is not empty; recur using the node's parent and decrement n by 1.
Below we write nthParent as a pure functional expression. To simplify the discussion to follow, we will define it function in curried form.
const Empty =
Symbol ()
const nthParent = (node = Empty) => (n = 0) =>
n === 0
? node
: node === Empty
? undefined // or some kind of error; this node does not have a parent
: nthParent (node.parentNode) (n - 1)
const Node = (value = null, parentNode = Empty) =>
({ Node, value, parentNode })
const data =
Node (5, Node (4, Node (3, Node (2, Node (1)))))
console.log
( nthParent (data) (1) .value // 4
, nthParent (data) (2) .value // 3
, nthParent (data) (3) .value // 2
, nthParent (data) (6) // undefined
)
but what if...
So suppose you were running your program with a JavaScript interpreter that did not support direct recursion... now you have a use case for the combinators
To remove the call-by-name recursion, we wrap our entire function in another lambda whose parameter f (or name of your choosing) will be the recursion mechanism itself. It is a drop-in replacement for nthParent –
changes in bold
const nthParent = Y (f => (node = Empty) => (n = 0) =>
n === 0
? node
: node === Empty
? undefined
: nthParent f (node.parentNode) (n - 1))
Now we can define Y
const Y = f =>
f (Y (f))
And we can remove direct recursion in Y with U using a similar technique as before– changes in bold
const U = f =>
f (f)
const Y = U (g => f =>
f (Y U (g) (f)))
But in order for it to work in JavaScript, which uses applicative order evaluation, we must delay evaluation using eta expansion – changes in bold
const U = f =>
f (f)
const Y = U (g => f =>
f (x => U (g) (f) (x)))
All together now
const U = f =>
f (f)
const Y = U (g => f =>
f (x => U (g) (f) (x)))
const Empty =
Symbol ()
const nthParent = Y (f => (node = Empty) => (n = 0) =>
n === 0
? node
: node === Empty
? undefined // or some kind of error; this node does not have a parent
: f (node.parentNode) (n - 1))
const Node = (value = null, parentNode = Empty) =>
({ Node, value, parentNode })
const data =
Node (5, Node (4, Node (3, Node (2, Node (1)))))
console.log
( nthParent (data) (1) .value // 4
, nthParent (data) (2) .value // 3
, nthParent (data) (3) .value // 2
, nthParent (data) (6) // undefined
)
Now I hope you see why the Y combinator exists and why you wouldn't use it in JavaScript. In another answer, I attempt to help readers gain a deeper intuition about the Y combinator by use of a mirror analogy. I invite you to read it if the topic interests you.
getting practical
It doesn't make sense to use the Y combinator when JavaScript already supports direct recursion. Below, see a more practical definition of nthParent in uncurried form
const nthParent = (node = Empty, n = 0) =>
n === 0
? node
: node === Empty
? undefined // or some kind of error; this node does not have a parent
: nthParent (node.parentNode, n - 1)
But what about those maximum recursion depth stack overflow errors? If we had a deep tree with nodes thousands of levels deep, the above function will produce such an error. In this answer I introduce several ways to work around the problem. It is possible to write stack-safe recursive functions in a language that doesn't support direct recursion and/or tail call elimination!
If imperative programming is an option:
function getParent(el, n){
while(n--) el = el.parentNode;
return el;
}
Using functional recursion you could do:
const Y = f => x => f (Y (f)) (x); // thanks to #Naomik
const getParent = Y(f => el => n => n ? f(el.parentNode)(n - 1) : el);
console.log(getParent(document.getElementById("test"))(5));
Lets build this Y-Combinator from the ground up.
As it calls a function by the Y-Combinator of itself, the Y-Combinator needs a reference to itself. For that we need a U-Combinator first:
(U => U(U))
Now we can call that U combinator with our Y combinator so that it gets a self reference:
(U => U(U))
(Y => f => f( Y(Y)(f) ))
However that has a problem: The function gets called with an Y-Combinator reference which gets called with a Y-Combinator reference wich gets called .... weve got Infinite recursion. Naomik outlined that here. The solution for that is to add another curried argument(e.g. x) that gets called when the function is used, and then another recursive combinator is created. So we only get the amount of recursion we actually need:
(U => U(U))
(Y => f => x => f( Y(Y)(f) )(x) )
(f => n => n ? f(n - 1): n)(10) // a small example
We could also restructure it like this:
(f => (U => U(U))(Y => f(x => Y(Y)(x))))
(f => n => n ? f(n - 1): n)(10) // a small example
To get your first snippet, so basically its the same thing just a bit reordered and obfuscated through shadowing.
So now another combinator gets only created when f(n-1) gets called, which only happens when n?, so weve got an exit condition now. Now we can finally add our node to the whole thing:
(U => U(U))
(Y => f => x => f( Y(Y)(f) )(x) )
(f => el => n => n ? f(el.parentNode)(n - 1): el)
(document.getElementById("test"))(10)
That would be purely functional, however that is not really useful as it is extremely complicated to use. If we store function references we dont need the U combinator as we can simply take the Y reference. Then we arrive at the snippet above.

ES6 double arrow parameters (i.e. const update = x => y => { } ) [duplicate]

This question already has answers here:
javascript es6 double arrow functions
(2 answers)
Closed 5 years ago.
What does double arrow parameters mean in the following code?
const update = x => y => {
// Do something with x and y
}
How is it different compared to the following?
const update = (x, y) => {
// Do something with x and y
}
Thanks!
Let's rewrite them "old style", the first one is:
const update = function (x) {
return function(y) {
// Do something with x and y
};
};
While the second one is:
const update = function (x, y) {
// Do something with x and y
};
So as you can see they are quite different, the first returns an "intermediate" function, while the second is a single function with two parameters.
There's nothing special about "double arrow parameters", this is just one arrow function returning another, and can be extended for as many arguments as you'd like. It's a technique called "currying".
From Wikipedia:
In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument.
The benefit of this is that it makes it easier to partially apply and compose functions, which is useful for some styles of functional programming.
Example
Let's say you have a function add which takes two numbers and adds them together, which you might traditionally write like this:
const add = (a, b) => a + b;
Now let's say you have an array of numbers and want to add 2 to all of them. Using map and the function above, you can do it like this:
[1, 2, 3].map(x => add(2, x));
However, if the function had been in curried form, you wouldn't need to wrap the call to add in another arrow function just to adapt the function to what map expects. Instead you could just do this:
const add = a => b => a + b;
[1, 2, 3].map(add(2));
This is of course a trivial and rather contrived example, but it shows the essence of it. Making it easier to partially apply functions also makes it more practical to write small and flexible functions that can be composed together, which then enables a much more "functional" style of programming.
That are called arrow functions, it the new format for functions presented by ES6, in the first example
const update = x => y => {
// Do something with x and y
}
can be traduced to
var update = function (x){
return function (y){
// Do something with x and y..
}
}
in ES5, and is a function that returns a function
is totally different than
const update = function (x, y) {
// Do something with x and y
};
The syntax PARAM => EXPR represents a function that takes a parameter PARAM and whose body is { return EXPR; }. It is itself an expression, so it can be used as the EXPR of other functions:
x => y => { ... }
parses as
x => (y => { ... })
which is the same as
x => { return y => { ... }; }

Is it possible to define an infix function?

Is it possible to define my own infix function/operator in CoffeeScript (or in pure JavaScript)? e.g. I want to call
a foo b
or
a `foo` b
instead of
a.foo b
or, when foo is global function,
foo a, b
Is there any way to do this?
ES6 enables a very Haskell/Lambda calculus way of doing things.
Given a multiplication function:
const multiply = a => b => (a * b)
You can define a doubling function using partial application (you leave out one parameter):
const double = multiply (2)
And you can compose the double function with itself, creating a quadruple function:
const compose = (f, g) => x => f(g(x))
const quadruple = compose (double, double)
But indeed, what if you would prefer an infix notation? As Steve Ladavich noted, you do need to extend a prototype.
But I think it can be done a bit more elegant using array notation instead of dot notation.
Lets use the official symbol for function composition "∘":
Function.prototype['∘'] = function(f){
return x => this(f(x))
}
const multiply = a => b => (a * b)
const double = multiply (2)
const doublethreetimes = (double) ['∘'] (double) ['∘'] (double)
console.log(doublethreetimes(3));
Actually adding this as an answer: no, this is not possible.
It's not possible in vanilla JS.
It's not possible in CoffeeScript.
You can with sweet.js. See:
http://sweetjs.org/doc/main/sweet.html#infix-macros
http://sweetjs.org/doc/main/sweet.html#custom-operators
Sweet.js extends Javascript with macros.
It acts like a preprocessor.
This is definitely not infix notation but it's kinda close : /
let plus = function(a,b){return a+b};
let a = 3;
let b = 5;
let c = a._(plus).b // 8
I don't think anyone would actually want to use this "notation" since it's pretty ugly, but I think there are probably some tweaks that can be made to make it look different or nicer (possibly using this answer here to "call a function" without parentheses).
Infix function
// Add to prototype so that it's always there for you
Object.prototype._ = function(binaryOperator){
// The first operand is captured in the this keyword
let operand1 = this;
// Use a proxy to capture the second operand with "get"
// Note that the first operand and the applied function
// are stored in the get function's closure, since operand2
// is just a string, for eval(operand2) to be in scope,
// the value for operand2 must be defined globally
return new Proxy({},{
get: function(obj, operand2){
return binaryOperator(operand1, eval(operand2))
}
})
}
Also note that the second operand is passed as a string and evaluated with eval to get its value. Because of this, I think the code will break anytime the value of operand (aka "b") is not defined globally.
Javascript doesn't include an infix notation for functions or sections for partial application. But it ships with higher order functions, which allow us to do almost everything:
// applicator for infix notation
const $ = (x, f, y) => f(x) (y);
// for left section
const $_ = (x, f) => f(x);
// for right section
const _$ = (f, y) => x => f(x) (y);
// non-commutative operator function
const sub = x => y => x - y;
// application
console.log(
$(2, sub, 3), // -1
$_(2, sub) (3), // -1
_$(sub, 3) (2) // -1
);
As you can see I prefer visual names $, $_ and _$ to textual ones in this case. This is the best you can get - at least with pure Javascript/ES2015.
You can get close by function currying:
const $ = (a) => (f) => f(a);
const plus = (a) => (b) => (a+b);
const twoPlusThree = $ (2) (plus) (3);
But I still haven't figured out a neat way to compose this construction.

Categories

Resources