Function vs fat arrow [duplicate] - javascript

This question already has answers here:
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 5 years ago.
So, if we take this function for example:
function executeCallback (callback) {
callback();
}
Now, it doesn't matter if I place a fat arrow or a normal function, both will work, like these:
executeCallback(function () {
alert('This is a function');
})
executeCallback(() => {
alert('This is a fat arrow function');
})
So, except for shorter syntax. What exactly is the difference between both and how does it effect object oriented programming?

For more in depth info, see this answer on SO. Also, See this here.
A Few Reasons
More intuitive handling of current object context.
ES6 Arrow
this.nums.forEach((v) => {
if (v % 5 === 0)
this.fives.push(v) //this actually points to the context of the callback
});
Ecmascript 5
// variant 1
var self = this;
this.nums.forEach(function (v) {
if (v % 5 === 0)
self.fives.push(v);
});
// variant 2
this.nums.forEach(function (v) {
if (v % 5 === 0)
this.fives.push(v);
}, this);
// variant 3 (since ECMAScript 5.1 only)
this.nums.forEach(function (v) {
if (v % 5 === 0)
this.fives.push(v);
}.bind(this));
More expressive closure syntax.
ES6 Arrow
odds = evens.map(v => v + 1)
pairs = evens.map(v => ({ even: v, odd: v + 1 }))
nums = evens.map((v, i) => v + i)
Ecmascript 5
odds = evens.map(function (v) { return v + 1; });
pairs = evens.map(function (v) { return { even: v, odd: v + 1 }; });
nums = evens.map(function (v, i) { return v + i; });

the arrow function automatically bind the current context to the this so you won't need to do myfunction.bind(this, args)

Related

Using filter() to implemnt curriable() in javascript is fial , however, uisng map() is work, why?

I'm trying to implement the curry() with placeholder support, that is curriable. curriable provides a high performance and small footprint curry method. The version1 is the working code
is using map in the recursion function. However, I tried to use filter to filter the placeholder in the version2! Using filter is good for most cases, but fail with case curriedJoin(_,_,3,4)(1,_)(2,5) withe reason Uncaught TypeError: curriedJoin(...)(...) is not a function, can any one tell me why?
version 1
/**
* #param { (...args: any[]) => any } fn
* #returns { (...args: any[]) => any }
*/
// function curry(fn) {
// // your code here
// }
function curry(func) {
return function curried(...args) {
const complete = args.length >= func.length && !args.slice(0, func.length).includes(curry.placeholder);
if(complete) {
args.length=3
args.sort((a,b)=>a-b)
return func.apply(this, args)
}
return function(...newArgs) {
// replace placeholders in args with values from newArgs using map
const res = args.map(arg => arg === curry.placeholder && newArgs.length ? newArgs.shift() : arg);
return curried(...res, ...newArgs);
}
}
}
const join = (a, b, c) => {
return `${a}_${b}_${c}`
}
curry.placeholder = Symbol()
const curriedJoin = curry(join)
const _ = curry.placeholder
console.log(curriedJoin(1, 2, 3)) // '1_2_3'
console.log(curriedJoin(_, 2)(1, 3)) // '1_2_3'
console.log(curriedJoin(_, _, _)(1)(_, 3)(2)) // '1_2_3'
console.log(curriedJoin(_,_,3,4)(1,_)(2,5))// '1_2_3'
Version2
/**
* #param { (...args: any[]) => any } fn
* #returns { (...args: any[]) => any }
*/
// function curry(fn) {
// // your code here
// }
function curry(func) {
return function curried(...args) {
const complete = args.length >= func.length && !args.slice(0, func.length).includes(curry.placeholder);
if(complete) {
args.length=3
args.sort((a,b)=>a-b)
return func.apply(this, args)
}
return function(...newArgs) {
// replace placeholders in args with values from newArgs
const res = [...args].filter(element=> element!== curry.placeholder);
return curried(...res, ...newArgs);
}
}
}
const join = (a, b, c) => {
return `${a}_${b}_${c}`
}
curry.placeholder = Symbol()
const curriedJoin = curry(join)
const _ = curry.placeholder
console.log(curriedJoin(1, 2, 3)) // '1_2_3'
console.log(curriedJoin(_, 2)(1, 3)) // '1_2_3'
console.log(curriedJoin(_, _, _)(1)(_, 3)(2)) // '1_2_3'
console.log(curriedJoin(_,_,3,4)(1,_)(2,5)) //Fail, because "Uncaught TypeError: curriedJoin(...)(...) is not a function"
If you add
console.log(curriedJoin(_,_,3,4)(1,_));
just before the failing line, you'll see that curriedJoin(_, _, 3, 4)(1, _) has already resolved to the string "1_3_4" ...which is not a function. Hence the error. The two versions behave quite differently (logging the various arg lists during processing is instructive.) The problem with using the "filter and append" approach is that it's not putting the args in the correct order. For the failing example, after one iteration, the 3rd placeholder ends up at the end of the arg list, beyond where the "complete" test is checking, instead of in the 2nd position where it belongs. What happens when filtering is that (_, _, 3, 4)(1, _) becomes (3,4,1,_), but the func only expects 3 good args, so this looks "complete" - oops! When using the "map" algorithm, (_, _, 3, 4)(1, _) becomes (1, _, 3, 4) which is clearly incomplete, so it goes into another recursion level as desired.
Use of .sort involves comparison of argument values and will not apply arguments with respect to their applied positions. Use of args.length = 3 will support only functions with 3 parameters.
Adding parameter n = f.length supports currying of fixed-arity functions as well as variadic functions. Adding curry.merge with sound inductive reasoning simplifies merging arguments and reduces complexity of curry.
function curry(f, n = f.length) {
return function loop(...args) {
const a = args.slice(0, n)
return a.some(v => v === curry.placeholder)
? (...b) => loop(...curry.merge(a, b))
: f(...a)
}
}
curry.placeholder = Symbol("curry.placeholder")
curry.merge = (l, r) =>
l.length == 0 && r.length == 0
? []
: l.length == 0
? r
: r.length == 0
? l
: l[0] === curry.placeholder
? [r[0], ...curry.merge(l.slice(1), r.slice(1))]
: [l[0], ...curry.merge(l.slice(1), r)]
const _ = curry.placeholder
const add = curry((a,b,c) => a + b + c)
console.log(add(1, 2, 3)) // 6
console.log(add(_, 2)(1, 3)) // 6
console.log(add(_, _, _)(1)(_, 3)(2)) // 6
console.log(add(_,_,3,4)(1,_)(2,5)) // 6
const foo = curry(console.log, 3)
foo(1, 2, 3) // 1 2 3
foo(_, 2)(1, 3) // 1 2 3
foo(_, _, _)(1)(_, 3)(2) // 1 2 3
foo(_,_,3,4)(1,_)(2,5) // 1 2 3
Maybe a better name for curry is partial as the technique you are using here is more closely related to Partial Application.

How to add the function n number of arguments in Javascript? add(3)(8)(6)(10) [duplicate]

This question already has answers here:
Variadic curried sum function
(19 answers)
How to curry a function across an unknown number of parameters
(7 answers)
Closed 4 years ago.
I need to add the function n number of arguments. Example : add(3)(8)(6)(10).
if it is only 2 arguments we can add the code like this. add(4)(5)
function add(x){
return function(y){
return x+y;
}
}
add(4)(5)
if it is n number of arguments of how can we do this?
The closer I can get to what you asked is this;
function add(x){
var next = function(y){
return add(x + y)
}
next.result = x
return next
}
console.log(add(4)(5).result)
console.log(add(4)(5)(1)(5).result)
console.log(add(3).result)
Here is a slightly different approach using objects, and IMO it is a lot more readable then add(1)(2)(3) since it is clear what operation you are performing in the subsequent steps. Also, this approach allows for extending with more operations, like minus for example.
class Add {
constructor (value) {
this.value = value
}
add (anotherValue) {
return new Add(this.value + anotherValue)
}
result () {
return this.value
}
}
function add (value) {
return new Add(value)
}
var result = add(3).add(5).add(10).result()
console.log(result) // 18
If n is not known beforehand, I can say categorically it's not possible. If n is fixed, you can do something like (say, n is 4):
const add = first => second => third => fourth => first + second + third + fourth.
If you want to let n be flexible, your best bet is this
const add = (...additives) => {
let result = 0;
for (const additive of additives) {
result += additive;
}
return result;
}
As Ryan suggested in his comment : add(3)(8)(6)(10) is impossible.
Try this work around :
function add() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum = sum+arguments[i];
}
return sum;
}
var res = add(3, 8, 6, 10);
console.log(res);

Arrow function not working but anonymous function does? [duplicate]

This question already has answers here:
Official information on `arguments` in ES6 Arrow functions?
(2 answers)
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 5 years ago.
I have the following code
function coroutine(g) {
var it = g();
return () => it.next.apply(it, arguments);
// also tried () => { return it.next.apply(it, arguments);
}
var run = coroutine(function* () {
var x = 1 + (yield);
var y = 1 + (yield);
yield (x + y);
});
And the following testing has been executed.
run()
{value: undefined, done: false}
run(10)
{value: undefined, done: false}
run(30).value
"1function* () { var x = 1 + (yield); var y = 1 + (yield); yield (x + y);}1function* () { var x = 1 + (yield); var y = 1 + (yield); yield (x + y);}"
However, shouldn't the last run(30).value returns the value of 42?
However, it works after I change the arrow function to old anonymous function?
function coroutine(g) {
var it = g();
return function() { return it.next.apply(it, arguments) };
}

ES6 arrow function returns undefined instead of desired value [duplicate]

This question already has answers here:
When should I use a return statement in ES6 arrow functions
(6 answers)
Closed 10 months ago.
Easy function that works in JS without ES6:
var evenOrOdd = function(n){
if(n % 2 == 1){
return "Odd";
} else {
return "Even";
}
}
console.log(evenOrOdd(3)); //returns odd
My attempt at restructuring this using ES6:
const evenOrOdd = (n) => {(n % 2 == 1) ? "Odd" : "Even"};
console.log(evenOrOdd(3)); //returns undefined
I'm following these examples here: 2ality and stoimen.
Why is this arrow function returning undefined?
You have to remove the {}.
const evenOrOdd = n => (n % 2 === 1 ? "odd" : "even")
console.log(evenOrOdd(3)) //=> "odd"
(It may help others)
I'm trying to return a value from nested function, which is wrong
const isEmailExistsInDb = usrEmail => {
userModel.countDocuments( {"email": usrEmail}, function (err, count){
return tempCount > 0;
});
};
Correct one is, have to return value from parent function
const isEmailExistsInDb = usrEmail => {
let tempCount;
mongoModel.countDocuments( {"email": usrEmail}, function (err, count){
tempCount = count;
});
// count > 0 if document exists
return tempCount > 0;
};

How can I make var a = add(2)(3); //5 work?

I want to make this syntax possible:
var a = add(2)(3); //5
based on what I read at http://dmitry.baranovskiy.com/post/31797647
I've got no clue how to make it possible.
You need add to be a function that takes an argument and returns a function that takes an argument that adds the argument to add and itself.
var add = function(x) {
return function(y) { return x + y; };
}
function add(x) {
return function(y) {
return x + y;
};
}
Ah, the beauty of JavaScript
This syntax is pretty neat as well
function add(x) {
return function(y) {
if (typeof y !== 'undefined') {
x = x + y;
return arguments.callee;
} else {
return x;
}
};
}
add(1)(2)(3)(); //6
add(1)(1)(1)(1)(1)(1)(); //6
It's about JS curring and a little strict with valueOf:
function add(n){
var addNext = function(x) {
return add(n + x);
};
addNext.valueOf = function() {
return n;
};
return addNext;
}
console.log(add(1)(2)(3)==6);//true
console.log(add(1)(2)(3)(4)==10);//true
It works like a charm with an unlimited adding chain!!
function add(x){
return function(y){
return x+y
}
}
First-class functions and closures do the job.
function add(n) {
sum = n;
const proxy = new Proxy(function a () {}, {
get (obj, key) {
return () => sum;
},
apply (receiver, ...args) {
sum += args[1][0];
return proxy;
},
});
return proxy
}
Works for everything and doesn't need the final () at the end of the function like some other solutions.
console.log(add(1)(2)(3)(10)); // 16
console.log(add(10)(10)); // 20
try this will help you in two ways add(2)(3) and add(2,3)
1.)
function add(a){ return function (b){return a+b;} }
add(2)(3) // 5
2.)
function add(a,b){
var ddd = function (b){return a+b;};
if(typeof b =='undefined'){
return ddd;
}else{
return ddd(b);
}
}
add(2)(3) // 5
add(2,3) // 5
ES6 syntax makes this nice and simple:
const add = (a, b) => a + b;
console.log(add(2, 5));
// output: 7
const add2 = a => b => a + b;
console.log(add2(2)(5));
// output: 7
Arrow functions undoubtedly make it pretty simple to get the required result:
const Sum = a => b => b ? Sum( a + b ) : a;
console.log(Sum(3)(4)(2)(5)()); //14
console.log(Sum(3)(4)(1)()); //8
This is a generalized solution which will solve add(2,3)(), add(2)(3)() or any combination like add(2,1,3)(1)(1)(2,3)(4)(4,1,1)(). Please note that few security checks are not done and it can be optimized further.
function add() {
var total = 0;
function sum(){
if( arguments.length ){
var arr = Array.prototype.slice.call(arguments).sort();
total = total + arrayAdder(arr);
return sum;
}
else{
return total;
}
}
if(arguments.length) {
var arr1 = Array.prototype.slice.call(arguments).sort();
var mytotal = arrayAdder(arr1);
return sum(mytotal);
}else{
return sum();
}
function arrayAdder(arr){
var x = 0;
for (var i = 0; i < arr.length; i++) {
x = x + arr[i];
};
return x;
}
}
add(2,3)(1)(1)(1,2,3)();
This will handle both
add(2,3) // 5
or
add(2)(3) // 5
This is an ES6 curry example...
const add = (a, b) => (b || b === 0) ? a + b : (b) => a + b;
This is concept of currying in JS.
Solution for your question is:
function add(a) {
return function(b) {
return a + b;
};
}
This can be also achieved using arrow function:
let add = a => b => a + b;
solution for add(1)(2)(5)(4)........(n)(); Using Recursion
function add(a) {
return function(b){
return b ? add(a + b) : a;
}
}
Using ES6 Arrow function Syntax:
let add = a => b => b ? add(a + b) : a;
in addition to what's already said, here's a solution with generic currying (based on http://github.com/sstephenson/prototype/blob/master/src/lang/function.js#L180)
Function.prototype.curry = function() {
if (!arguments.length) return this;
var __method = this, args = [].slice.call(arguments, 0);
return function() {
return __method.apply(this, [].concat(
[].slice.call(args, 0),
[].slice.call(arguments, 0)));
}
}
add = function(x) {
return (function (x, y) { return x + y }).curry(x)
}
console.log(add(2)(3))
Concept of CLOSURES can be used in this case.
The function "add" returns another function. The function being returned can access the variable in the parent scope (in this case variable a).
function add(a){
return function(b){
console.log(a + b);
}
}
add(2)(3);
Here is a link to understand closures http://www.w3schools.com/js/js_function_closures.asp
const add = a => b => b ? add(a+b) : a;
console.log(add(1)(2)(3)());
Or (`${a} ${b}`) for strings.
With ES6 spread ... operator and .reduce function. With that variant you will get chaining syntax but last call () is required here because function is always returned:
function add(...args) {
if (!args.length) return 0;
const result = args.reduce((accumulator, value) => accumulator + value, 0);
const sum = (...innerArgs) => {
if (innerArgs.length === 0) return result;
return add(...args, ...innerArgs);
};
return sum;
}
// it's just for fiddle output
document.getElementById('output').innerHTML = `
<br><br>add() === 0: ${add() === 0 ? 'true' : 'false, res=' + add()}
<br><br>add(1)(2)() === 3: ${add(1)(2)() === 3 ? 'true' : 'false, res=' + add(1)(2)()}
<br><br>add(1,2)() === 3: ${add(1,2)() === 3 ? 'true' : 'false, res=' + add(1,2)()}
<br><br>add(1)(1,1)() === 3: ${add(1)(1,1)() === 3 ? 'true' : 'false, res=' + add(1)(1,1)()}
<br><br>add(2,3)(1)(1)(1,2,3)() === 13: ${add(2,3)(1)(1)(1,2,3)() === 13 ? 'true' : 'false, res=' + add(2,3)(1)(1)(1,2,3)()}
`;
<div id='output'></div>
can try this also:
let sum = a => b => b ? sum(a + b) :a
console.log(sum(10)(20)(1)(32)()) //63
const sum = function (...a) {
const getSum = d => {
return d.reduce((i,j)=> i+j, 0);
};
a = getSum(a);
return function (...b) {
if (b.length) {
return sum(a + getSum(b));
}
return a;
}
};
console.log(sum(1)(2)(3)(4,5)(6)(8)())
function add(a, b){
return a && b ? a+b : function(c){return a+c;}
}
console.log(add(2, 3));
console.log(add(2)(3));
This question has motivated so many answers already that my "two pennies worth" will surely not spoil things.
I was amazed by the multitude of approaches and variations that I tried to put "my favourite" features, i. e. the ones that I would like to find in such a currying function together, using some ES6 notation:
const add=(...n)=>{
const vsum=(a,c)=>a+c;
n=n.reduce(vsum,0);
const fn=(...x)=>add(n+x.reduce(vsum,0));
fn.toString=()=>n;
return fn;
}
let w=add(2,1); // = 3
console.log(w()) // 3
console.log(w); // 3
console.log(w(6)(2,3)(4)); // 18
console.log(w(5,3)); // 11
console.log(add(2)-1); // 1
console.log(add()); // 0
console.log(add(5,7,9)(w)); // 24
.as-console-wrapper {max-height:100% !important; top:0%}
Basically, nothing in this recursively programmed function is new. But it does work with all possible combinations of arguments mentioned in any of the answers above and won't need an "empty arguments list" at the end.
You can use as many arguments in as many currying levels you want and the result will be another function that can be reused for the same purpose. I used a little "trick" to also get a numeric value "at the same time": I redefined the .toString() function of the inner function fn! This method will be called by Javascript whenever the function is used without an arguments list and "some value is expected". Technically it is a "hack" as it will not return a string but a number, but it will work in a way that is in most cases the "desired" way. Give it a spin!
Simple Recursion Solution for following use cases
add(); // 0
add(1)(2)(); //3
add(1)(2)(3)(); //6
function add(v1, sum = 0) {
if (!v1) return sum;
sum += v1
return (v2) => add(v2, sum);
}
function add() {
var sum = 0;
function add() {
for (var i=0; i<arguments.length; i++) {
sum += Number(arguments[i]);
}
return add;
}
add.valueOf = function valueOf(){
return parseInt(sum);
};
return add.apply(null,arguments);
}
// ...
console.log(add() + 0); // 0
console.log(add(1) + 0);/* // 1
console.log(add(1,2) + 0); // 3
function A(a){
return function B(b){
return a+b;
}
}
I found a nice explanation for this type of method. It is known as Syntax of Closures
please refer this link
Syntax of Closures
Simply we can write a function like this
function sum(x){
return function(y){
return function(z){
return x+y+z;
}
}
}
sum(2)(3)(4)//Output->9
Don't be complicated.
var add = (a)=>(b)=> b ? add(a+b) : a;
console.log(add(2)(3)()); // Output:5
it will work in the latest javascript (ES6), this is a recursion function.
Here we use concept of closure where all the functions called inside main function iter refer and udpate x as they have closure over it. no matter how long the loop goes , till last function , have access to x.
function iter(x){
return function innfunc(y){
//if y is not undefined
if(y){
//closure over ancestor's x
x = y+x;
return innfunc;
}
else{
//closure over ancestor's x
return x;
}
}
}
iter(2)(3)(4)() //9
iter(1)(3)(4)(5)() //13
let multi = (a)=>{
return (b)=>{
return (c)=>{
return a*b*c
}
}
}
multi (2)(3)(4) //24
let multi = (a)=> (b)=> (c)=> a*b*c;
multi (2)(3)(4) //24
we can do this work using closure.
function add(param1){
return function add1(param2){
return param2 = param1 + param2;
}
}
console.log(add(2)(3));//5
I came up with nice solution with closure, inner function have access to parent function's parameter access and store in its lexical scope, when ever we execute it, will get answer
const Sum = function (a) {
return function (b) {
return b ? Sum(a + b) : a;
}
};
Sum(1)(2)(3)(4)(5)(6)(7)() // result is 28
Sum(3)(4)(5)() // result is 12
Sum(12)(10)(20) // result is 42
enter image description here
You should go in for currying to call the function in the above format.
Ideally, a function which adds two numbers will be like,
let sum = function(a, b) {
return a + b;
}
The same function can be transformed as,
let sum = function(a) {
return function(b) {
return a+b;
}
}
console.log(sum(2)(3));
Let us understand how this works.
When you invoke sum(2), it returns
function(b) {
return 2 + b;
}
when the returned function is further invoked with 3, b takes the value 3. The result 5 is returned.
More Detailed Explanation:
let sum = function(a) {
return function(b) {
return a + b;
}
}
let func1 = sum(2);
console.log(func1);
let func2 = func1(3)
console.log(func2);
//the same result can be obtained in a single line
let func3 = sum(2)(3);
console.log(func3);
//try comparing the three functions and you will get more clarity.
This is a short solution:
const add = a => b => {
if(!b) return a;
return add(a + b);
}
add(1)(2)(3)() // 6
add(1)(2)(3)(4)(5)() // 15

Categories

Resources