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

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 => { ... }; }

Related

Currying function with unknown arguments in JavaScript

In a recent interview, I was asked to write a function that adds numbers and accepts parameters like this:
add(1)(2)(3) // result is 6
add(1,2)(3,4)(5) // result is 15
The number of parameters is not fixed, and the arguments can be either passed in sets or individually.
How can I implement this add function?
Given your examples, the number of parameters is fixed in some ways.
As #ASDFGerte pointed out, your examples seem to return the result after three invocations. In this case a simple implementation without introducing terms like variadic and currying could be
function add(...args1){
return function(...args2){
return function(...args3){
return args1.concat(args2).concat(args3).reduce((a,b)=>a+b)}}}
console.log(add(1)(2)(3))
console.log(add(1,2)(3,4)(5))
Every invocation accepts a variable number of parameters.
However it would be nice to generalize the construction of this nested functions structure and you can accomplish that with currying.
But if you want to allow an arbitrary number of invocations, when you should stop returning a new function and return the result? There is no way to know, and this is a simple, unaccurate and partial explanation to give you the idea of why they said you cannot accomplish what they asked you.
So the ultimate question is: is it possible that you misunderstood the question? Or maybe it was just a trick to test you
Edit
Another option would be to actually invoke the function when no arguments are passed in, change the call to add(1)(2)(3)()
Here an example recursive implementation
function sum (...args) {
let s = args.reduce((a,b)=>a+b)
return function (...x) {
return x.length == 0 ? s : sum(s, ...x)
};
}
console.log(sum(1,2)(2,3,4)(2)())
At every invocation computes the sum of current parameters and then return a new function that:
if is invoked without parameters just return the current sum
if other numbers are passed in, invokes recursively sum passing the actual sum and the new numbers
I'm a bit late to the party, but something like this would work (a bit hacky though in my opinion):
const add = (a, ...restA) => {
const fn = (b, ...restB) => {
return add([a, ...restA].reduce((x, y) => x + y) + [b, ...restB].reduce((x, y) => x + y))
};
fn.valueOf = () => {
return [a, ...restA].reduce((x, y) => x + y)
};
return fn;
}
This function returns a function with a value of the sum. The tests below are outputing the coerced values instead of the actual functions.
console.log(+add(1,2)(3,4)(5)); // 15
console.log(+add(1)) // 1
console.log(+add(1)(2)) // 3
console.log(+add(1)(2)(3)) // 6
console.log(+add(1)(2)(3)(4)) // 10
Since it's a currying function, it will always return another function so you can do something like this:
const addTwo = add(2);
console.log(+addTwo(5)); // 7
using reduce and spread it can be done as below
function calc(...args1){
return function (...args2){
return function (...args3){
let merge = [...args1, ...args2, ...args3]
return merge.reduce((x ,y)=> x + y) ;
}
}
}
let sum = calc(10)(1)(4);
console.log("sum",sum);
They probably wanted to know how comfortable you were with "javascript internals", such as how and when methods like Function#toString and Function#valueOf, Function#[Symbol.toPrimitive] are called under the hood.
const add = (...numbers) => {
const cadd = (...args) => add(...args, ...numbers);
cadd[Symbol.toPrimitive] = () => numbers.reduce((a, b) => a + b);
return cadd;
}
console.log(
`add(1,2)(3,4)(5) =>`, add(1,2)(3,4)(5),
); // result is 15
console.log(
`add(1,2) =>`, add(1,2),
); // result is 3
console.log(
`add(1,2)(5)(1,2)(5)(1,2)(5)(1,2)(5) =>`, add(1,2)(5)(1,2)(5)(1,2)(5)(1,2)(5),
); // result is 32

ES6 arrow functions returning different values

I'm new to ES6 and I'm trying to figure out what the difference is between this:
const func1 = (x, y) => x * y * 3
and this:
const func2 = x => y => x * y * 3
I have tried running it and I see that the func1(1,1) returns 3 and func2(1) returns 1.
What are the differences and benefits of one or the other?
In what circumstances would you use func2?
Can someone demonstrate how you would use func2?
const func1 = (x, y) => x * y * 3 is a standard arrow function that translates to this:
const func1 = function (x,y) {
return x * y * 3;
}
Whereas,
const func2 = x => y => x * y * 3 is a curried function where you have a function within another function like this:
const func2 = function (x) {
return function (y) {
return x * y * 3;
}
And yeah, as CRice mentioned below, you have to call the parameters spearately with func2 like this:
console.log(func2(a)(b));
As opposed to the standard:
console.log(func1(a,b));
Currying is useful in both practical and theoretical settings. In
functional programming languages, and many others, it provides a way
of automatically managing how arguments are passed to functions and
exceptions. In theoretical computer science, it provides a way to
study functions with multiple arguments in simpler theoretical models
which provide only one argument.
So func2 is a function that can be used in situations where for example, you have to return an 'abc' message if certain requirements are met or run a new function with a different logic if the initial requirements are not met.
Quoted Section via - Wikipedia | Currying
Function two is a curried version of function one. That means that instead of taking a pair of arguments, you pass the first argument in, and it will return you a new function to which you can pass the second argument separately.
Curried functions are useful for creating partially applied functions, among other things. So for your example, you might use those function like so:
const func1 = (x, y) => x * y * 3
const func2 = x => y => x * y * 3
// Two different calling syntaxes, same result:
console.log(func1(2, 3)) // 18
console.log(func2(2)(3)) // 18, note the call chain: (2)(3).
// This is because func2 returns another function.
// You can use that function to partially apply your operation:
const times6 = func2(2);
// Then you can use that elsewhere:
console.log(times6(3)); // 18
console.log(times6(10)); // 60

Javascript : What is the difference between these two fat arrow functions? [duplicate]

This question already has an answer here:
Where can I get info on the object parameter syntax for JavaScript functions?
(1 answer)
Closed 5 years ago.
const f = ({x,y})=>{...do something...};
const f = (x,y)=>{...do something...};
What is the difference between these two lines ?
My understanding is both pass "x" and "y" are arguments.
Are both the same then ?
The first one uses destructuring you can use it as
f({x: 0, y: 1})
you pass one object with fields x and y
and then in body you can access fields of object as variables x and y.
In the second one you have to pass 2 variables
f(0, 1)
Bodies can be the same of those functions and they would work analogically
for instance
=> { return x + y; }
but params should be passed in different ways
The first one you're passing an object as a parameter. But I don't think it's a working example. Here is one
class O {
x;
y;
}
const example =(o:O)=>{
//do something
return o.x+o.y;
};
The equivalent is
var example = function example(o) {
//do something
return o.x+o.y;
};
The second one you're passing two parameters the equivalent is
var example2 = function example2(x, y) {
//do something
return 0;
};

What would be a good example of an endofunctor that is not the identity functor?

In Professor Frisby Introduces Composable Functional JavaScript the identity functor was introduced:
const Box = x =>
({
map: f => Box(f(x)),
fold: f => f(x) // for testing
})
I spent the better part of the day understanding functors and why the above JavaScript code is actually the identity functor. So I thought I would alter it to get a "real" functor that is not the identity functor. I came up with this:
const Endo = x =>
({
map: f => Endo(f(x).split('')),
fold: f => f(x).split('') // for testing
})
My reasoning is that with Box, Id_Box: Box -> Box and Id_Box f = f. Endo would also map to itself but Endo(f): Endo(x) -> Endo(y) (if f: x -> y).
Am I on the right track?
EDIT:
Replaced string with the more generic x as it was in the original examples.
As pointed out in this answer, for our purposes as programmers we can treat all functors as endofunctors so don't get too caught up on the differences.
As for what a functor is, in brief it is
a data structure (Box in your example)
that can support a mapping operation (think Array.prototype.map)
and that mapping operation respects identity: xs === xs.map(x => x)
...and composition: xs.map(f).map(g) === xs.map(f . g) where . is function composition.
That's it. No more, no less. Looking at your Box, it's a data structure that has a map function (check 1 & 2) and that map function looks like it should respect identity and composition (check 3 & 4). So it's a functor. But it doesn't do anything, which is why it's the identity functor. The fold function isn't strictly necessary, it just provides a way to 'unwrap' the box.
For a useful functor, let's look at JavaScript arrays. Arrays actually do something: namely they contain multiple values rather than just a single one. If an array could only have one element, it'd be your Box. For our purposes we'll pretend that they can only hold values of the same type to simply things. So an array is a data structure, that has a map function, that respects identity and composition.
let plus = x => y => x + y;
let mult = x => y => x * y;
let plus2 = plus(2);
let times3 = mult(3);
let id = x => x;
let compose = (...fs) => arg => fs.reverse().reduce((x, f) => { return f(x) }, arg);
// Here we need to stringify the arrays as JS will compare on
// ref rather than value. I'm omitting it after the first for
// brevity, but know that it's necessary.
[1,2,3].map(plus2).toString() === [3,4,5].toString(); // true
[1,2,3].map(id) === [1,2,3]; // true
[1,2,3].map(plus2).map(times3) === [1,2,3].map(compose(times3, plus2)); // true
So when we map a function over a functor (array) we get back another instance of the same functor (a new Array) with the function applied to whatever the functor (array) was holding.
So now lets look at another ubiquitous JavaScript data structure, the object. There's no built in map function for objects. Can we make them a functor? Assume again that the object is homogenous (only has keys to one type of value, in this example Number):
let mapOverObj = obj => f => {
return Object.entries(obj).reduce((newObj, [key, value]) => {
newObj[key] = f(value);
return newObj;
}, {});
};
let foo = { 'bar': 2 };
let fooPrime = mapOverObj(foo)(plus2); // { 'bar': 4 }
And you can continue on to test that the function accurately (as far as is possible in JavaScript) supports identity and composition to satisfy the functor laws.

Are 'currying' and 'composition' the same concept in Javascript?

Recently I read about function composition in a Javascript book, and then on a website I saw someone reference it as currying.
Are they the same concept?
#Omarjmh's answer is good but the compose example is overwhelmingly complex for a learner, in my opinion
Are they the same concept?
No.
First, currying is translating a function that takes multiple arguments into a sequence of functions, each accepting one argument.
// not curried
const add = (x,y) => x + y;
add(2,3); // => 5
// curried
const add = x => y => x + y;
add(2)(3); // => 5
Notice the distinct way in which a curried function is applied, one argument at a time.
Second, function composition is the combination of two functions into one, that when applied, returns the result of the chained functions.
const compose = f => g => x => f(g(x));
compose (x => x * 4) (x => x + 3) (2);
// (2 + 3) * 4
// => 20
The two concepts are closely related as they play well with one another. Generic function composition works with unary functions (functions that take one argument) and curried functions also only accept one argument (per application).
// curried add function
const add = x => y => y + x;
// curried multiplication function
const mult = x => y => y * x;
// create a composition
// notice we only apply 2 of comp's 3 parameters
// notice we only apply 1 of mult's 2 parameters
// notice we only apply 1 of add's 2 parameters
let add10ThenMultiplyBy3 = compose (mult(3)) (add(10));
// apply the composition to 4
add10ThenMultiplyBy3(4); //=> 42
// apply the composition to 5
add10ThenMultiplyBy3(5); //=> 45
Composition and currying are used to create functions. Composition and currying differ in the way they create new functions (by applying args vs chaining).
Compose:
Compose should return a function that is the composition of a list of functions of arbitrary length. Each function is called on the return value of the function that follows. You can think of compose as moving right to left through its arguments.
Example:
var compose = function(funcs) {
funcs = Array.prototype.slice.call(arguments, 0);
return function(arg) {
return funcs.reduceRight(function (a, b) {
a = a === null ? a = b(arg) : a = b(a);
return a;
}, null);
};
};
var sayHi = function(name){ return 'hi: ' + name;};
var makeLouder = function(statement) { return statement.toUpperCase() + '!';};
var hello = compose(sayHi, makeLouder);
l(hello('Johhny')); //=> 'hi: JOHNNY!'
Currying:
Currying is a way of constructing functions that allows partial application of a function’s arguments.
Example:
var addOne = add(1);
var addTwo = add(2);
var addOneToFive = addOne(5);
var addTwoToFive = addTwo(5);
l(addOneToFive); //6
l(addTwoToFive); //7
JSBin with the above examples:
https://jsbin.com/jibuje/edit?js,console

Categories

Resources